Skip to content

Commit 22e3fc4

Browse files
jpnurmiclaude
andcommitted
fix(retry): prevent UB from negative count in backoff shift
Reject negative counts in parse_filename (a corrupted filename like 123--01-<uuid>.envelope parses count=-1 via strtol). Also clamp the count in sentry__retry_backoff to prevent left-shift by a negative amount. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 37faf28 commit 22e3fc4

3 files changed

Lines changed: 37 additions & 2 deletions

File tree

src/sentry_retry.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ sentry__retry_parse_filename(const char *filename, uint64_t *ts_out,
6767

6868
const char *count_str = end + 1;
6969
long count = strtol(count_str, &end, 10);
70-
if (*end != '-') {
70+
if (*end != '-' || count < 0) {
7171
return false;
7272
}
7373

@@ -87,7 +87,7 @@ sentry__retry_parse_filename(const char *filename, uint64_t *ts_out,
8787
uint64_t
8888
sentry__retry_backoff(int count)
8989
{
90-
return (uint64_t)SENTRY_RETRY_INTERVAL << MIN(count, 5);
90+
return (uint64_t)SENTRY_RETRY_INTERVAL << MIN(MAX(count, 0), 5);
9191
}
9292

9393
typedef struct {

tests/unit/test_retry.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,39 @@ test_send_cb(sentry_envelope_t *envelope, void *_ctx)
8080
return ctx->status_code;
8181
}
8282

83+
SENTRY_TEST(retry_filename)
84+
{
85+
uint64_t ts;
86+
int count;
87+
const char *uuid;
88+
89+
TEST_CHECK(sentry__retry_parse_filename(
90+
"1234567890-00-abcdefab-1234-5678-9abc-def012345678.envelope", &ts,
91+
&count, &uuid));
92+
TEST_CHECK_UINT64_EQUAL(ts, 1234567890);
93+
TEST_CHECK_INT_EQUAL(count, 0);
94+
TEST_CHECK(strncmp(uuid, "abcdefab-1234-5678-9abc-def012345678", 36) == 0);
95+
96+
TEST_CHECK(sentry__retry_parse_filename(
97+
"999-04-abcdefab-1234-5678-9abc-def012345678.envelope", &ts, &count,
98+
&uuid));
99+
TEST_CHECK_UINT64_EQUAL(ts, 999);
100+
TEST_CHECK_INT_EQUAL(count, 4);
101+
102+
// negative count
103+
TEST_CHECK(!sentry__retry_parse_filename(
104+
"123--01-abcdefab-1234-5678-9abc-def012345678.envelope", &ts, &count,
105+
&uuid));
106+
107+
// cache filename (no timestamp/count)
108+
TEST_CHECK(!sentry__retry_parse_filename(
109+
"abcdefab-1234-5678-9abc-def012345678.envelope", &ts, &count, &uuid));
110+
111+
// missing .envelope suffix
112+
TEST_CHECK(!sentry__retry_parse_filename(
113+
"123-00-abcdefab-1234-5678-9abc-def012345678.txt", &ts, &count, &uuid));
114+
}
115+
83116
SENTRY_TEST(retry_throttle)
84117
{
85118
SENTRY_TEST_OPTIONS_NEW(options);
@@ -353,6 +386,7 @@ SENTRY_TEST(retry_backoff)
353386
TEST_CHECK_UINT64_EQUAL(sentry__retry_backoff(4), base * 16);
354387
TEST_CHECK_UINT64_EQUAL(sentry__retry_backoff(5), base * 32);
355388
TEST_CHECK_UINT64_EQUAL(sentry__retry_backoff(6), base * 32);
389+
TEST_CHECK_UINT64_EQUAL(sentry__retry_backoff(-1), base);
356390

357391
sentry__retry_free(retry);
358392
sentry_close();

tests/unit/tests.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ XX(read_write_envelope_to_invalid_path)
166166
XX(recursive_paths)
167167
XX(retry_backoff)
168168
XX(retry_cache)
169+
XX(retry_filename)
169170
XX(retry_result)
170171
XX(retry_session)
171172
XX(retry_throttle)

0 commit comments

Comments
 (0)