Handle memory allocation failures when unformatting data
[silc.git] / lib / silcutil / silcbuffmt.c
index 20285ec84e4465f63d5c8e132bdef06b1595f72f..98836b61768a3771c2b8a7059db6e7cab728b0d3 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2006 Pekka Riikonen
+  Copyright (C) 1997 - 2007 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 
 /* Check that buffer has enough room to format data in it, if not
    allocate more. */
-#define FORMAT_HAS_SPACE(s, b, req)            \
-do {                                           \
-  if (!silc_buffer_senlarge(s, b, req))                \
-    goto fail;                                 \
-  flen += req;                                 \
+#define FORMAT_HAS_SPACE(s, b, req)                    \
+do {                                                   \
+  if (silc_unlikely(!silc_buffer_senlarge(s, b, req))) \
+    goto fail;                                         \
+  flen += req;                                         \
 } while(0)
 
 /* Check that there is data to be unformatted */
 #define UNFORMAT_HAS_SPACE(b, req)             \
 do {                                           \
-  if (req > silc_buffer_len(b))                        \
+  if (silc_unlikely(req > silc_buffer_len(b))) \
     goto fail;                                 \
-  if ((req + 1) <= 0)                          \
+  if (silc_unlikely((req + 1) <= 0))           \
     goto fail;                                 \
 } while(0)
 
@@ -85,8 +85,8 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
     switch(fmt) {
     case SILC_PARAM_FUNC:
       {
-       SilcBufferFormatFunc func;
-       SilcBufferSFormatFunc funcs;
+       SilcBufferFormatFunc func = NULL;
+       SilcBufferSFormatFunc funcs = NULL;
        void *val;
        void *context;
        int tmp_len;
@@ -116,10 +116,12 @@ int silc_buffer_sformat_vp(SilcStack stack, SilcBuffer dst, va_list ap)
     case SILC_PARAM_UI32_STRING_ALLOC:
       {
        unsigned char *x = va_arg(ap, unsigned char *);
-       SilcUInt32 tmp_len = strlen(x);
-       FORMAT_HAS_SPACE(stack, dst, tmp_len);
-       silc_buffer_put(dst, x, tmp_len);
-       silc_buffer_pull(dst, tmp_len);
+       SilcUInt32 tmp_len = x ? strlen(x) : 0;
+       if (x && tmp_len) {
+         FORMAT_HAS_SPACE(stack, dst, tmp_len);
+         silc_buffer_put(dst, x, tmp_len);
+         silc_buffer_pull(dst, tmp_len);
+       }
        break;
       }
     case SILC_PARAM_UI8_NSTRING:
@@ -313,6 +315,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
   SilcBufferParamType fmt;
   unsigned char *start_ptr = src->data;
   int len = 0;
+  SilcBool advance = FALSE;
 
   /* Parse the arguments by formatting type. */
   while(1) {
@@ -321,8 +324,8 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
     switch(fmt) {
     case SILC_PARAM_FUNC:
       {
-       SilcBufferUnformatFunc func;
-       SilcBufferSUnformatFunc funcs;
+       SilcBufferUnformatFunc func = NULL;
+       SilcBufferSUnformatFunc funcs = NULL;
        void **val;
        void *context;
        int tmp_len;
@@ -349,7 +352,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 len2 = va_arg(ap, SilcUInt32);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (len2 && x)
+       if (silc_likely(len2 && x))
          *x = src->data;
        silc_buffer_pull(src, len2);
        break;
@@ -360,9 +363,10 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        unsigned char **x = va_arg(ap, unsigned char **);
        SilcUInt32 len2 = va_arg(ap, SilcUInt32);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (len2 && x) {
+       if (silc_likely(len2 && x)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
@@ -371,7 +375,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        unsigned char *x = va_arg(ap, unsigned char *);
        UNFORMAT_HAS_SPACE(src, 1);
-       if (x)
+       if (silc_likely(x))
          *x = src->data[0];
        silc_buffer_pull(src, 1);
        break;
@@ -380,7 +384,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        SilcUInt16 *x = va_arg(ap, SilcUInt16 *);
        UNFORMAT_HAS_SPACE(src, 2);
-       if (x)
+       if (silc_likely(x))
          SILC_GET16_MSB(*x, src->data);
        silc_buffer_pull(src, 2);
        break;
@@ -389,7 +393,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        SilcUInt32 *x = va_arg(ap, SilcUInt32 *);
        UNFORMAT_HAS_SPACE(src, 4);
-       if (x)
+       if (silc_likely(x))
          SILC_GET32_MSB(*x, src->data);
        silc_buffer_pull(src, 4);
        break;
@@ -398,7 +402,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        SilcUInt64 *x = va_arg(ap, SilcUInt64 *);
        UNFORMAT_HAS_SPACE(src, sizeof(SilcUInt64));
-       if (x)
+       if (silc_likely(x))
          SILC_GET64_MSB(*x, src->data);
        silc_buffer_pull(src, sizeof(SilcUInt64));
        break;
@@ -407,7 +411,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        char *x = va_arg(ap, char *);
        UNFORMAT_HAS_SPACE(src, 1);
-       if (x)
+       if (silc_likely(x))
          *x = src->data[0];
        silc_buffer_pull(src, 1);
        break;
@@ -416,7 +420,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        SilcInt16 *x = va_arg(ap, SilcInt16 *);
        UNFORMAT_HAS_SPACE(src, 2);
-       if (x)
+       if (silc_likely(x))
          SILC_GET16_MSB(*x, src->data);
        silc_buffer_pull(src, 2);
        break;
@@ -425,7 +429,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        SilcInt32 *x = va_arg(ap, SilcInt32 *);
        UNFORMAT_HAS_SPACE(src, 4);
-       if (x)
+       if (silc_likely(x))
          SILC_GET32_MSB(*x, src->data);
        silc_buffer_pull(src, 4);
        break;
@@ -434,7 +438,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
       {
        SilcInt64 *x = va_arg(ap, SilcInt64 *);
        UNFORMAT_HAS_SPACE(src, sizeof(SilcInt64));
-       if (x)
+       if (silc_likely(x))
          SILC_GET64_MSB(*x, src->data);
        silc_buffer_pull(src, sizeof(SilcInt64));
        break;
@@ -447,7 +451,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        len2 = (SilcUInt8)src->data[0];
        silc_buffer_pull(src, 1);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (x)
+       if (silc_likely(x))
          *x = src->data;
        silc_buffer_pull(src, len2);
        break;
@@ -460,7 +464,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        SILC_GET16_MSB(len2, src->data);
        silc_buffer_pull(src, 2);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (x)
+       if (silc_likely(x))
          *x = src->data;
        silc_buffer_pull(src, len2);
        break;
@@ -473,9 +477,10 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        len2 = (SilcUInt8)src->data[0];
        silc_buffer_pull(src, 1);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (x && len2) {
+       if (silc_likely(x && len2)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
@@ -488,9 +493,10 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        SILC_GET16_MSB(len2, src->data);
        silc_buffer_pull(src, 2);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (x && len2) {
+       if (silc_likely(x && len2)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
@@ -503,7 +509,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (x)
+       if (silc_likely(x))
          *x = src->data;
        silc_buffer_pull(src, len2);
        break;
@@ -516,9 +522,10 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        UNFORMAT_HAS_SPACE(src, len2);
-       if (x && len2) {
+       if (silc_likely(x && len2)) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
@@ -568,7 +575,8 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
          *len3 = len2;
        if (x && len2) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
@@ -586,7 +594,8 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
          *len3 = len2;
        if (x && len2) {
          *x = silc_scalloc(stack, len2 + 1, sizeof(unsigned char));
-         memcpy(*x, src->data, len2);
+         if (*x)
+           memcpy(*x, src->data, len2);
        }
        silc_buffer_pull(src, len2);
        break;
@@ -627,9 +636,10 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        SILC_GET32_MSB(len2, src->data);
        silc_buffer_pull(src, 4);
        UNFORMAT_HAS_SPACE(src, len2);
-       silc_buffer_sformat(stack, x,
-                           SILC_STR_DATA(src->data, len2),
-                           SILC_STR_END);
+       if (silc_buffer_sformat(stack, x,
+                               SILC_STR_DATA(src->data, len2),
+                               SILC_STR_END) < 0)
+         goto fail;
        silc_buffer_pull(src, len2);
       }
       break;
@@ -647,6 +657,7 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
        break;
       }
     case SILC_PARAM_ADVANCE:
+      advance = TRUE;
       break;
     case SILC_PARAM_END:
       goto ok;
@@ -660,15 +671,17 @@ int silc_buffer_sunformat_vp(SilcStack stack, SilcBuffer src, va_list ap)
   }
 
  fail:
-  SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
+  SILC_LOG_DEBUG(("Error occured while unformatting buffer, type %d", fmt));
   len = src->data - start_ptr;
   silc_buffer_push(src, len);
   return -1;
 
  ok:
   /* Push the buffer back to the start. */
-  len = src->data - start_ptr;
-  silc_buffer_push(src, len);
+  if (!advance) {
+    len = src->data - start_ptr;
+    silc_buffer_push(src, len);
+  }
   return len;
 }
 
@@ -698,7 +711,7 @@ int silc_buffer_strformat(SilcBuffer dst, ...)
 
     slen = strlen(string);
     d = silc_realloc(dst->head, sizeof(*dst->head) * (slen + len + 1));
-    if (!d)
+    if (silc_unlikely(!d))
       return -1;
     dst->head = d;
     memcpy(dst->head + len, string, slen);
@@ -741,9 +754,9 @@ int silc_buffer_sstrformat(SilcStack stack, SilcBuffer dst, ...)
       goto ok;
 
     slen = strlen(string);
-    d = silc_srealloc_ua(stack, len + 1, dst->head,
-                        sizeof(*dst->head) * (slen + len + 1));
-    if (!d)
+    d = silc_srealloc(stack, len + 1, dst->head,
+                     sizeof(*dst->head) * (slen + len + 1));
+    if (silc_unlikely(!d))
       return -1;
     dst->head = d;
     memcpy(dst->head + len, string, slen);