Two unrelated issues but touching the same are of code: - For Visual Studio, we use the '#define snprint _snprintf' macro, but _snprinft isn't C99 compliant, and in particularly will not NUL terminate if the buffer isn't large enough. So 0 terminate explicitly - In json_escape_str / json_object_int_to_json_string a static char[] buffer is used. This isn't thread-safe. Just use a plain char[]pull/331/head
| @@ -143,15 +143,16 @@ static int json_escape_str(struct printbuf *pb, const char *str, int len, int fl | |||||
| default: | default: | ||||
| if(c < ' ') | if(c < ' ') | ||||
| { | { | ||||
| char sbuf[7]; | |||||
| if(pos - start_offset > 0) | if(pos - start_offset > 0) | ||||
| printbuf_memappend(pb, | printbuf_memappend(pb, | ||||
| str + start_offset, | str + start_offset, | ||||
| pos - start_offset); | pos - start_offset); | ||||
| static char sbuf[7]; | |||||
| snprintf(sbuf, sizeof(sbuf), | snprintf(sbuf, sizeof(sbuf), | ||||
| "\\u00%c%c", | "\\u00%c%c", | ||||
| json_hex_chars[c >> 4], | json_hex_chars[c >> 4], | ||||
| json_hex_chars[c & 0xf]); | json_hex_chars[c & 0xf]); | ||||
| sbuf[sizeof(sbuf)-1] = '\0'; | |||||
| printbuf_memappend_fast(pb, sbuf, (int) sizeof(sbuf) - 1); | printbuf_memappend_fast(pb, sbuf, (int) sizeof(sbuf) - 1); | ||||
| start_offset = ++pos; | start_offset = ++pos; | ||||
| } else | } else | ||||
| @@ -589,8 +590,9 @@ static int json_object_int_to_json_string(struct json_object* jso, | |||||
| int flags) | int flags) | ||||
| { | { | ||||
| /* room for 19 digits, the sign char, and a null term */ | /* room for 19 digits, the sign char, and a null term */ | ||||
| static char sbuf[21]; | |||||
| char sbuf[21]; | |||||
| snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64); | snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64); | ||||
| sbuf[sizeof(sbuf)-1] = '\0'; | |||||
| return printbuf_memappend (pb, sbuf, strlen(sbuf)); | return printbuf_memappend (pb, sbuf, strlen(sbuf)); | ||||
| } | } | ||||
| @@ -749,6 +751,7 @@ static int json_object_double_to_json_string_format(struct json_object* jso, | |||||
| NaN or Infinity as numeric values | NaN or Infinity as numeric values | ||||
| ECMA 262 section 9.8.1 defines | ECMA 262 section 9.8.1 defines | ||||
| how to handle these cases as strings */ | how to handle these cases as strings */ | ||||
| buf[sizeof(buf)-1] = '\0'; | |||||
| if(isnan(jso->o.c_double)) | if(isnan(jso->o.c_double)) | ||||
| size = snprintf(buf, sizeof(buf), "NaN"); | size = snprintf(buf, sizeof(buf), "NaN"); | ||||
| else if(isinf(jso->o.c_double)) | else if(isinf(jso->o.c_double)) | ||||
| @@ -82,6 +82,7 @@ void _set_last_err(const char *err_fmt, ...) | |||||
| va_start(ap, err_fmt); | va_start(ap, err_fmt); | ||||
| // Ignore (attempted) overruns from snprintf | // Ignore (attempted) overruns from snprintf | ||||
| (void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap); | (void)vsnprintf(_last_err, sizeof(_last_err), err_fmt, ap); | ||||
| _last_err[sizeof(_last_err)-1] = '\0'; | |||||
| va_end(ap); | va_end(ap); | ||||
| } | } | ||||
| @@ -270,7 +271,8 @@ int json_parse_int64(const char *buf, int64_t *retval) | |||||
| if (num64 == 0) // assume all sscanf impl's will parse -0 to 0 | if (num64 == 0) // assume all sscanf impl's will parse -0 to 0 | ||||
| orig_has_neg = 0; // "-0" is the same as just plain "0" | orig_has_neg = 0; // "-0" is the same as just plain "0" | ||||
| snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); | |||||
| snprintf(buf_cmp, sizeof(buf_cmp), "%" PRId64, num64); | |||||
| buf_cmp[sizeof(buf_cmp)-1] = '\0'; | |||||
| if (*buf_cmp_start == '-') | if (*buf_cmp_start == '-') | ||||
| { | { | ||||
| recheck_has_neg = 1; | recheck_has_neg = 1; | ||||
| @@ -120,13 +120,14 @@ int sprintbuf(struct printbuf *p, const char *msg, ...) | |||||
| /* user stack buffer first */ | /* user stack buffer first */ | ||||
| va_start(ap, msg); | va_start(ap, msg); | ||||
| size = vsnprintf(buf, 128, msg, ap); | |||||
| size = vsnprintf(buf, sizeof(buf), msg, ap); | |||||
| buf[sizeof(buf)-1] = '\0'; | |||||
| va_end(ap); | va_end(ap); | ||||
| /* if string is greater than stack buffer, then use dynamic string | /* if string is greater than stack buffer, then use dynamic string | ||||
| with vasprintf. Note: some implementation of vsnprintf return -1 | with vasprintf. Note: some implementation of vsnprintf return -1 | ||||
| if output is truncated whereas some return the number of bytes that | if output is truncated whereas some return the number of bytes that | ||||
| would have been written - this code handles both cases. */ | would have been written - this code handles both cases. */ | ||||
| if(size == -1 || size > 127) { | |||||
| if(size == -1 || size > (int)sizeof(buf)-1) { | |||||
| va_start(ap, msg); | va_start(ap, msg); | ||||
| if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } | if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } | ||||
| va_end(ap); | va_end(ap); | ||||