Selaa lähdekoodia

fix: json库的encode函数在系统内存不够的时候,会崩溃的情况,正确处理应该是终止输出,返回nil

Wendal Chen 3 vuotta sitten
vanhempi
sitoutus
30f0e2b24b
3 muutettua tiedostoa jossa 69 lisäystä ja 137 poistoa
  1. 29 13
      components/lua-cjson/lua_cjson.c
  2. 31 121
      components/lua-cjson/strbuf.c
  3. 9 3
      components/lua-cjson/strbuf.h

+ 29 - 13
components/lua-cjson/lua_cjson.c

@@ -56,6 +56,9 @@
 
 #define MIN_OPT_LEVEL 2
 
+#define LUAT_LOG_TAG "json"
+#include "luat_log.h"
+
 //#include <lrodefs.h>
 //#include <auxmods.h>
 
@@ -442,6 +445,8 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
      * If there are any excess pages, they won't be hit anyway.
      * This gains ~5% speedup. */
     strbuf_ensure_empty_length(json, len * 6 + 2);
+    if (json->is_err)
+        return;
 
     strbuf_append_char_unsafe(json, '\"');
     for (i = 0; i < len; i++) {
@@ -588,6 +593,8 @@ static void json_append_number(lua_State *l,
     }
 
     strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);
+    if (json->is_err)
+        return;
     if (lua_isinteger(l, lindex)) {
         len = snprintf_(strbuf_empty_ptr(json), FPCONV_G_FMT_BUFSIZE, "%ld", lua_tointeger(l, lindex));
     }
@@ -698,26 +705,31 @@ static int json_encode(lua_State *l)
     strbuf_t *encode_buf;
     char *json;
     int len;
+    int ret;
 
     luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
 
-    // if (!DEFAULT_ENCODE_KEEP_BUFFER) {
-        /* Use private buffer */
-        encode_buf = &local_encode_buf;
-        strbuf_init(encode_buf, 0);
-    // } else {
-    //     /* Reuse existing buffer */
-    //     encode_buf = &cfg->encode_buf;
-    //     strbuf_reset(encode_buf);
-    // }
+    
+    encode_buf = &local_encode_buf;
+    ret = strbuf_init(encode_buf, 0);
+    if (ret) {
+        LLOGE("json encode out of memory!!!");
+        return 0;
+    }
 
     json_append_data(l, 0, encode_buf);
-    json = strbuf_string(encode_buf, &len);
 
-    lua_pushlstring(l, json, len);
+    // check if err
+    if (local_encode_buf.is_err) {
+        LLOGE("json encode failed by memory less");
+        lua_pushnil(l);
+    }
+    else {
+        json = strbuf_string(encode_buf, &len);
+        lua_pushlstring(l, json, len);
+    }
 
-    // if (!cfg->encode_keep_buffer)
-        strbuf_free(encode_buf);
+    strbuf_free(encode_buf);
 
     return 1;
 }
@@ -1295,6 +1307,10 @@ static int json_decode(lua_State *l)
      * This means we no longer need to do length checks since the decoded
      * string must be smaller than the entire json string */
     json.tmp = strbuf_new(json_len);
+    if (json.tmp == NULL) {
+        LLOGE("json decode out of memory!");
+        return 0;
+    }
 
     json_next_token(&json, &token);
     json_process_value(l, &json, &token);

+ 31 - 121
components/lua-cjson/strbuf.c

@@ -42,13 +42,7 @@
 #define L_FREE  luat_heap_free
 #define L_REALLOC  luat_heap_realloc
 
-static void die(const char *fmt, ...)
-{
-    LLOGD("%s", fmt);
-    exit(-1);
-}
-
-void strbuf_init(strbuf_t *s, int len)
+int strbuf_init(strbuf_t *s, int len)
 {
     int size;
 
@@ -62,25 +56,31 @@ void strbuf_init(strbuf_t *s, int len)
     s->length = 0;
     s->increment = STRBUF_DEFAULT_INCREMENT;
     s->dynamic = 0;
-    s->reallocs = 0;
-    s->debug = 0;
+    // s->reallocs = 0;
+    // s->debug = 0;
 
     s->buf = (char *)L_MALLOC(size);
     if (!s->buf)
-        die("Out of memory");
+        return -1;
 
     strbuf_ensure_null(s);
+    return 0;
 }
 
 strbuf_t *strbuf_new(int len)
 {
     strbuf_t *s;
+    int ret = 0;
 
     s = (strbuf_t *)L_MALLOC(sizeof(strbuf_t));
     if (!s)
-        die("Out of memory");
+        return NULL;
 
-    strbuf_init(s, len);
+    ret = strbuf_init(s, len);
+    if (ret) {
+        L_FREE(s);
+        return NULL;
+    }
 
     /* Dynamic strbuf allocation / deallocation */
     s->dynamic = 1;
@@ -88,29 +88,11 @@ strbuf_t *strbuf_new(int len)
     return s;
 }
 
-void strbuf_set_increment(strbuf_t *s, int increment)
-{
-    /* Increment > 0:  Linear buffer growth rate
-     * Increment < -1: Exponential buffer growth rate */
-    if (increment == 0 || increment == -1)
-        die("BUG: Invalid string increment");
-
-    s->increment = increment;
-}
-
-static inline void debug_stats(strbuf_t *s)
-{
-    if (s->debug) {
-        fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %d, size: %d\n",
-                (long)s, s->reallocs, s->length, s->size);
-    }
-}
-
 /* If strbuf_t has not been dynamically allocated, strbuf_free() can
  * be called any number of times strbuf_init() */
 void strbuf_free(strbuf_t *s)
 {
-    debug_stats(s);
+    // debug_stats(s);
 
     if (s->buf) {
         L_FREE (s->buf);
@@ -120,30 +102,12 @@ void strbuf_free(strbuf_t *s)
         L_FREE (s);
 }
 
-char *strbuf_free_to_string(strbuf_t *s, int *len)
-{
-    char *buf;
-
-    debug_stats(s);
-
-    strbuf_ensure_null(s);
-
-    buf = s->buf;
-    if (len)
-        *len = s->length;
-
-    if (s->dynamic)
-        L_FREE (s);
-
-    return buf;
-}
-
 static int calculate_new_size(strbuf_t *s, int len)
 {
     int reqsize, newsize;
 
-    if (len <= 0)
-        die("BUG: Invalid strbuf length requested");
+    // if (len <= 0)
+    //     die("BUG: Invalid strbuf length requested");
 
     /* Ensure there is room for optional NULL termination */
     reqsize = len + 1;
@@ -153,16 +117,11 @@ static int calculate_new_size(strbuf_t *s, int len)
         return reqsize;
 
     newsize = s->size;
-    if (s->increment < 0) {
-        /* Exponential sizing */
-        while (newsize < reqsize)
-            newsize *= -s->increment;
-    } else {
-        /* Linear sizing */
-        newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
+    if (reqsize - s->size < 1023) {
+        reqsize = s->size + 1023;
     }
 
-    return newsize;
+    return reqsize + 1;
 }
 
 
@@ -171,24 +130,28 @@ static int calculate_new_size(strbuf_t *s, int len)
 void strbuf_resize(strbuf_t *s, int len)
 {
     int newsize;
+    void* ptr;
+
+    if (s->is_err)
+        return;
 
     newsize = calculate_new_size(s, len);
 
-    if (s->debug > 1) {
-        fprintf(stderr, "strbuf(%lx) resize: %d => %d\n",
-                (long)s, s->size, newsize);
+    ptr = (char *)L_REALLOC(s->buf, newsize);
+    if (ptr == NULL) {
+        s->is_err = 1;
+    }
+    else {
+        s->size = newsize;
+        s->buf = ptr;
     }
-
-    s->size = newsize;
-    s->buf = (char *)L_REALLOC(s->buf, s->size);
-    if (!s->buf)
-        die("Out of memory");
-    s->reallocs++;
 }
 
 void strbuf_append_string(strbuf_t *s, const char *str)
 {
     int space, i;
+    if (s->is_err)
+        return;
 
     space = strbuf_empty_length(s);
 
@@ -203,56 +166,3 @@ void strbuf_append_string(strbuf_t *s, const char *str)
         space--;
     }
 }
-
-/* strbuf_append_fmt() should only be used when an upper bound
- * is known for the output string. */
-void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
-{
-    va_list arg;
-    int fmt_len;
-
-    strbuf_ensure_empty_length(s, len);
-
-    va_start(arg, fmt);
-    fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
-    va_end(arg);
-
-    if (fmt_len < 0)
-        die("BUG: Unable to convert number");  /* This should never happen.. */
-
-    s->length += fmt_len;
-}
-
-/* strbuf_append_fmt_retry() can be used when the there is no known
- * upper bound for the output string. */
-void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
-{
-    va_list arg;
-    int fmt_len, try;
-    int empty_len;
-
-    /* If the first attempt to append fails, resize the buffer appropriately
-     * and try again */
-    for (try = 0; ; try++) {
-        va_start(arg, fmt);
-        /* Append the new formatted string */
-        /* fmt_len is the length of the string required, excluding the
-         * trailing NULL */
-        empty_len = strbuf_empty_length(s);
-        /* Add 1 since there is also space to store the terminating NULL. */
-        fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
-        va_end(arg);
-
-        if (fmt_len <= empty_len)
-            break;  /* SUCCESS */
-        if (try > 0)
-            die("BUG: length of formatted string changed");
-
-        strbuf_resize(s, s->length + fmt_len);
-    }
-
-    s->length += fmt_len;
-}
-
-/* vi:ai et sw=4 ts=4:
- */

+ 9 - 3
components/lua-cjson/strbuf.h

@@ -39,8 +39,9 @@ typedef struct {
     int length;
     int increment;
     int dynamic;
-    int reallocs;
-    int debug;
+    int is_err;
+    // int reallocs;
+    // int debug;
 } strbuf_t;
 
 #ifndef STRBUF_DEFAULT_SIZE
@@ -52,7 +53,7 @@ typedef struct {
 
 /* Initialise */
 extern strbuf_t *strbuf_new(int len);
-extern void strbuf_init(strbuf_t *s, int len);
+extern int strbuf_init(strbuf_t *s, int len);
 extern void strbuf_set_increment(strbuf_t *s, int increment);
 
 /* Release */
@@ -118,29 +119,34 @@ static inline int strbuf_length(strbuf_t *s)
 static inline void strbuf_append_char(strbuf_t *s, const char c)
 {
     strbuf_ensure_empty_length(s, 1);
+    if (s->is_err) return;
     s->buf[s->length++] = c;
 }
 
 static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
 {
+    if (s->is_err) return;
     s->buf[s->length++] = c;
 }
 
 static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
 {
     strbuf_ensure_empty_length(s, len);
+    if (s->is_err) return;
     memcpy(s->buf + s->length, c, len);
     s->length += len;
 }
 
 static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
 {
+    if (s->is_err) return;
     memcpy(s->buf + s->length, c, len);
     s->length += len;
 }
 
 static inline void strbuf_ensure_null(strbuf_t *s)
 {
+    if (s->is_err) return;
     s->buf[s->length] = 0;
 }