Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
- Structured logs: respect printf argument widths when extracting log parameters to avoid stack-data disclosure and corrupted attributes on 32-bit platforms. ([#1752](https://github.com/getsentry/sentry-native/pull/1752))
- Fix a potential out-of-bounds read when parsing non-NUL-terminated `sentry-trace` headers. ([#1749](https://github.com/getsentry/sentry-native/pull/1749))
- Fix division by zero when breadcrumbs are disabled. ([#1767](https://github.com/getsentry/sentry-native/pull/1767))
- Handle memory allocation failures during JSON serialization to prevent truncated output. ([#1772](https://github.com/getsentry/sentry-native/pull/1772))

## 0.14.2

Expand Down
76 changes: 52 additions & 24 deletions src/sentry_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@

typedef struct {
void (*free)(sentry_jsonwriter_t *writer);
void (*write_str)(sentry_jsonwriter_t *writer, const char *str);
void (*write_buf)(sentry_jsonwriter_t *writer, const char *buf, size_t len);
void (*write_char)(sentry_jsonwriter_t *writer, char c);
bool (*write_str)(sentry_jsonwriter_t *writer, const char *str);
bool (*write_buf)(sentry_jsonwriter_t *writer, const char *buf, size_t len);
bool (*write_char)(sentry_jsonwriter_t *writer, char c);
char *(*into_string)(sentry_jsonwriter_t *jw, size_t *len_out);
} sentry_jsonwriter_ops_t;

Expand All @@ -40,6 +40,7 @@ struct sentry_jsonwriter_s {
uint32_t depth;
bool last_was_key;
bool owns_sb;
bool failed;
sentry_jsonwriter_ops_t *ops;
};

Expand All @@ -65,40 +66,42 @@ jsonwriter_free_file(sentry_jsonwriter_t *jw)
sentry_free(jw);
}

static void
static bool
write_char_sb(sentry_jsonwriter_t *jw, char c)
{
sentry__stringbuilder_append_char(jw->output.sb, c);
return sentry__stringbuilder_append_char(jw->output.sb, c) == 0;
}

static void
static bool
write_str_sb(sentry_jsonwriter_t *jw, const char *str)
{
sentry__stringbuilder_append(jw->output.sb, str);
return sentry__stringbuilder_append(jw->output.sb, str) == 0;
}

static void
static bool
write_buf_sb(sentry_jsonwriter_t *jw, const char *buf, size_t len)
{
sentry__stringbuilder_append_buf(jw->output.sb, buf, len);
return sentry__stringbuilder_append_buf(jw->output.sb, buf, len) == 0;
}

static void
static bool
write_char_file(sentry_jsonwriter_t *jw, char c)
{
sentry__filewriter_write(jw->output.fw, &c, sizeof(char));
return sentry__filewriter_write(jw->output.fw, &c, sizeof(char)) == 0;
}

static void
static bool
write_str_file(sentry_jsonwriter_t *jw, const char *str)
{
sentry__filewriter_write(jw->output.fw, str, sizeof(char) * strlen(str));
return sentry__filewriter_write(
jw->output.fw, str, sizeof(char) * strlen(str))
== 0;
}

static void
static bool
write_buf_file(sentry_jsonwriter_t *jw, const char *buf, size_t len)
{
sentry__filewriter_write(jw->output.fw, buf, len);
return sentry__filewriter_write(jw->output.fw, buf, len) == 0;
}

static char *
Expand All @@ -107,9 +110,11 @@ into_string_sb(sentry_jsonwriter_t *jw, size_t *len_out)
char *rv = NULL;
sentry_stringbuilder_t *sb = jw->output.sb;
if (len_out) {
*len_out = sb->len;
*len_out = jw->failed ? 0 : sb->len;
}
if (!jw->failed) {
rv = sentry__stringbuilder_into_string(sb);
}
rv = sentry__stringbuilder_into_string(sb);
sentry__jsonwriter_free(jw);
return rv;
}
Expand Down Expand Up @@ -156,6 +161,7 @@ sentry__jsonwriter_new_sb(sentry_stringbuilder_t *sb)
rv->depth = 0;
rv->last_was_key = 0;
rv->owns_sb = owns_sb;
rv->failed = false;
rv->ops = &sb_ops;
return rv;
}
Expand All @@ -182,6 +188,7 @@ sentry__jsonwriter_new_fw(sentry_filewriter_t *fw)
rv->depth = 0;
rv->last_was_key = 0;
rv->owns_sb = owns_sb;
rv->failed = false;
rv->ops = &file_ops;
return rv;
}
Expand All @@ -198,6 +205,7 @@ sentry__jsonwriter_reset(sentry_jsonwriter_t *jw)
jw->want_comma = 0;
jw->depth = 0;
jw->last_was_key = 0;
jw->failed = false;
}

char *
Expand Down Expand Up @@ -228,13 +236,25 @@ set_comma(sentry_jsonwriter_t *jw, bool val)
static void
write_char(sentry_jsonwriter_t *jw, char c)
{
jw->ops->write_char(jw, c);
if (!jw->ops->write_char(jw, c)) {
jw->failed = true;
}
}

static void
write_str(sentry_jsonwriter_t *jw, const char *str)
{
jw->ops->write_str(jw, str);
if (!jw->ops->write_str(jw, str)) {
jw->failed = true;
}
}

static void
write_buf(sentry_jsonwriter_t *jw, const char *buf, size_t len)
{
if (!jw->ops->write_buf(jw, buf, len)) {
jw->failed = true;
}
}

// The Lookup table and algorithm below are adapted from:
Expand Down Expand Up @@ -270,14 +290,18 @@ write_json_str(sentry_jsonwriter_t *jw, const char *str)
write_char(jw, '"');

const unsigned char *start = ptr;
for (; *ptr; ptr++) {
for (; *ptr && !jw->failed; ptr++) {
if (!needs_escaping[*ptr]) {
continue;
}

size_t len = (size_t)(ptr - start);
if (len) {
jw->ops->write_buf(jw, (const char *)start, len);
write_buf(jw, (const char *)start, len);
}

if (jw->failed) {
return;
}

switch (*ptr) {
Expand Down Expand Up @@ -315,12 +339,16 @@ write_json_str(sentry_jsonwriter_t *jw, const char *str)
}
}

if (jw->failed) {
return;
}

start = ptr + 1;
}

size_t len = (size_t)(ptr - start);
if (len) {
jw->ops->write_buf(jw, (const char *)start, len);
write_buf(jw, (const char *)start, len);
}

write_char(jw, '"');
Expand All @@ -329,7 +357,7 @@ write_json_str(sentry_jsonwriter_t *jw, const char *str)
static bool
can_write_item(sentry_jsonwriter_t *jw)
{
if (at_max_depth(jw)) {
if (at_max_depth(jw) || jw->failed) {
return false;
}
if (jw->last_was_key) {
Expand All @@ -341,7 +369,7 @@ can_write_item(sentry_jsonwriter_t *jw)
} else {
set_comma(jw, true);
}
return true;
return !jw->failed;
}

void
Expand Down
Loading