Skip to content

fix: introduce malloc/MAKE rv checks if missing#1234

Merged
supervacuus merged 2 commits intomasterfrom
fix/check_malloc_and_make_returns
Jun 12, 2025
Merged

fix: introduce malloc/MAKE rv checks if missing#1234
supervacuus merged 2 commits intomasterfrom
fix/check_malloc_and_make_returns

Conversation

@supervacuus
Copy link
Collaborator

@supervacuus supervacuus commented May 12, 2025

#1224 raises the issue that there are still some unchecked returns from SENTRY_MAKE and sentry_malloc. This PR (now) fixes this first layer, but we should also fix the internal uses of all functions affected by early returns. For instance, here:

sentry_pathiter_t *piter = sentry__path_iter_directory(path);
const sentry_path_t *p;
while ((p = sentry__pathiter_next(piter)) != NULL) {
sentry__path_remove_all(p);
}
sentry__pathiter_free(piter);

path_iter could be NULL. Evaluating our coverage and keeping it would require a bit more work.

#skip-changelog

@getsentry getsentry deleted a comment from github-actions bot May 12, 2025
@getsentry getsentry deleted a comment from github-actions bot May 12, 2025
@supervacuus supervacuus force-pushed the fix/check_malloc_and_make_returns branch from a2a8e2c to 73816a2 Compare May 16, 2025 15:15
@supervacuus supervacuus force-pushed the fix/check_malloc_and_make_returns branch from 73816a2 to 7689a0c Compare June 11, 2025 14:25
@supervacuus supervacuus marked this pull request as ready for review June 12, 2025 06:59
@supervacuus
Copy link
Collaborator Author

@JoshuaMoelans, I started work on a CodeQL query that will support tracking issues like these, but I don't see why this should block merging this.

While in practice, it is very rare that malloc will return NULL without everything else also failing, it shouldn't be us that trigger a crash in monitored applications in case this happens.

However, it highlights a more significant phenomenon, which I would like to have a more basic support for: checking returned pointers at call sites (which can be NULL, independent of allocation failure). That is what CodeQL (or maybe infer) can help us with, but not in this PR (which already fixes the root checks).

Copy link
Member

@JoshuaMoelans JoshuaMoelans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, I just have one remark on a success/fail return value & two questions about applying the test changes more broadly.

Comment on lines +160 to +162
if (!libname) {
return 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(from the function's docstring above) why is a null-libname a success?

 /* Returns 1 on failure and 0 on success. "s" is the address of the symbol,
 * and "i" points to a Dl_info structure to fill. Note that i.dli_fname is
 * not const, and should be freed.
 */

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh, I didn't look at the inline docs. I examined the surrounding code, where every early exit returns 0, and the only success case I could find returns 1. Maybe I misread?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the docstring is just wrong, and it returns 1 on success and 0 on early exit/failure, so your addition is functionally correct 👌

for (size_t i = 0; i < 100; i++) {
sentry_bgworker_t *bgw = sentry__bgworker_new(NULL, NULL);
TEST_CHECK(!!bgw);
TEST_ASSERT(!!bgw);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Why do we only switch to TEST_ASSERT here? (Considering the docstring for it, aborting when no backgroundworker was created makes sense, but I just wonder if there might be more places where this change could be useful).

Copy link
Collaborator Author

@supervacuus supervacuus Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching from CHECK to ASSERT generally means that continuing and aggregating errors could lead to a crash in the test itself, which is almost always much more complicated to pinpoint than a failed assertion.

  • TEST_ASSERT and similar macros should be used whenever further execution could lead to trouble.
  • TEST_CHECK should be used whenever a result is wrong, but the remaining test can still execute cleanly.

The latter is preferred because this way we get to fix all errors in one iteration. However, the former is a necessity for running tests safely.

Comment on lines +160 to +162
if (!libname) {
return 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the docstring is just wrong, and it returns 1 on success and 0 on early exit/failure, so your addition is functionally correct 👌

@supervacuus supervacuus merged commit 16fa689 into master Jun 12, 2025
36 checks passed
@supervacuus supervacuus deleted the fix/check_malloc_and_make_returns branch June 12, 2025 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants