Add basic regress for JSON functions.

Fix a bug in escaped control character handling.
Roll back changes to buffer if sudo_json_add_value() fails.
This commit is contained in:
Todd C. Miller
2022-12-15 19:49:11 -07:00
parent 0e6482e827
commit 797cc917a8
12 changed files with 310 additions and 32 deletions

View File

@@ -164,7 +164,7 @@ json_append_string(struct json_container *jsonc, const char *str)
*cp++ = '0';
*cp++ = '0';
*cp++ = hex[ch >> 4];
ch &= 0x0f;
ch = hex[ch & 0x0f];
}
break;
}
@@ -180,8 +180,8 @@ json_append_string(struct json_container *jsonc, const char *str)
}
bool
sudo_json_init_v1(struct json_container *jsonc, int indent, bool minimal,
bool memfatal)
sudo_json_init_v2(struct json_container *jsonc, int indent, bool minimal,
bool memfatal, bool quiet)
{
debug_decl(sudo_json_init, SUDO_DEBUG_UTIL);
@@ -190,6 +190,7 @@ sudo_json_init_v1(struct json_container *jsonc, int indent, bool minimal,
jsonc->indent_increment = indent;
jsonc->minimal = minimal;
jsonc->memfatal = memfatal;
jsonc->quiet = quiet;
jsonc->buf = malloc(64 * 1024);
if (jsonc->buf == NULL) {
if (jsonc->memfatal) {
@@ -206,6 +207,13 @@ sudo_json_init_v1(struct json_container *jsonc, int indent, bool minimal,
debug_return_bool(true);
}
bool
sudo_json_init_v1(struct json_container *jsonc, int indent, bool minimal,
bool memfatal)
{
return sudo_json_init_v2(jsonc, indent, minimal, memfatal, false);
}
void
sudo_json_free_v1(struct json_container *jsonc)
{
@@ -309,69 +317,83 @@ static bool
sudo_json_add_value_int(struct json_container *jsonc, const char *name,
struct json_value *value, bool as_object)
{
struct json_container saved_container = *jsonc;
char numbuf[(((sizeof(long long) * 8) + 2) / 3) + 2];
debug_decl(sudo_json_add_value, SUDO_DEBUG_UTIL);
/* Add comma if we are continuing an object/array. */
if (jsonc->need_comma) {
if (!json_append_buf(jsonc, ","))
debug_return_bool(false);
goto bad;
}
if (!json_new_line(jsonc))
debug_return_bool(false);
goto bad;
jsonc->need_comma = true;
if (as_object) {
if (!json_append_buf(jsonc, jsonc->minimal ? "{" : "{ "))
debug_return_bool(false);
goto bad;
}
/* name */
if (name != NULL) {
if (!json_append_string(jsonc, name))
debug_return_bool(false);
goto bad;
if (!json_append_buf(jsonc, jsonc->minimal ? ":" : ": "))
debug_return_bool(false);
goto bad;
}
/* value */
switch (value->type) {
case JSON_STRING:
if (!json_append_string(jsonc, value->u.string))
debug_return_bool(false);
goto bad;
break;
case JSON_ID:
snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)value->u.id);
if (!json_append_buf(jsonc, numbuf))
debug_return_bool(false);
goto bad;
break;
case JSON_NUMBER:
snprintf(numbuf, sizeof(numbuf), "%lld", value->u.number);
if (!json_append_buf(jsonc, numbuf))
debug_return_bool(false);
goto bad;
break;
case JSON_NULL:
if (!json_append_buf(jsonc, "null"))
debug_return_bool(false);
goto bad;
break;
case JSON_BOOL:
if (!json_append_buf(jsonc, value->u.boolean ? "true" : "false"))
debug_return_bool(false);
goto bad;
break;
case JSON_ARRAY:
sudo_fatalx("internal error: can't print JSON_ARRAY");
break;
if (!jsonc->quiet)
sudo_warnx("internal error: add JSON_ARRAY as a value");
goto bad;
case JSON_OBJECT:
sudo_fatalx("internal error: can't print JSON_OBJECT");
break;
if (!jsonc->quiet)
sudo_warnx("internal error: add JSON_OBJECT as a value");
goto bad;
default:
if (!jsonc->quiet)
sudo_warnx("internal error: unknown JSON type %d", value->type);
goto bad;
}
if (as_object) {
if (!json_append_buf(jsonc, jsonc->minimal ? "}" : " }"))
debug_return_bool(false);
goto bad;
}
debug_return_bool(true);
bad:
/* Restore container but handle reallocation of buf. */
saved_container.buf = jsonc->buf;
saved_container.bufsize = jsonc->bufsize;
*jsonc = saved_container;
jsonc->buf[jsonc->buflen] = '\0';
debug_return_bool(false);
}
bool