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); | ||||