-
Notifications
You must be signed in to change notification settings - Fork 195
trace2: stop allowing die() #2178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
8463471
bd45f46
ec447a6
db6858d
7f0bb40
120cf19
c8fc195
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #ifndef BANNED_DIE_H | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elijah Newren wrote on the Git mailing list (how to reply to this email): On Tue, Aug 25, 2026 at 11:58 AM Derrick Stolee via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
[...]
> +#undef die
> +#define die banned(die)
Shouldn't that be BANNED(die) to match all the other cases in the code
(and avoid an obtuse "implicit declaration of function 'banned'"
instead of the nicer "sorry_die_is_a_banned_function" message)?
> +
> +#endif /* BANNED_DIE_H */
> diff --git a/trace2.c b/trace2.c
> index c23c0a227b..1d0ed2db2b 100644
> --- a/trace2.c
> +++ b/trace2.c
> @@ -17,6 +17,7 @@
> #include "trace2/tr2_tgt.h"
> #include "trace2/tr2_tls.h"
> #include "trace2/tr2_tmr.h"
> +#include "banned-die.h"
>
Is there a risk that future folks add new includes at the end of the
list, then functions in them get added to banned-die.h, but are
silently ignored because banned-die.h wasn't the last include? |
||
| #define BANNED_DIE_H | ||
|
|
||
| #include "banned.h" | ||
|
|
||
| /* | ||
| * This header lists functions that must not be used by low-level APIs | ||
| * because they can cause Git to terminate. | ||
| */ | ||
|
|
||
| #undef die | ||
| #define die banned(die) | ||
|
|
||
| #undef xsnprintf | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elijah Newren wrote on the Git mailing list (how to reply to this email): On Tue, Aug 25, 2026 at 11:58 AM Derrick Stolee via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
[...]
> For full defense in depth, we remove the xstrdup() calls from
> trace2/tr2_sysenv.c.
>
> First, in tr2_sysenv_cb(), we need to handle a failed assignment of the
> value with a negative return to halt the config parsing loop.
>
[...]
> --- a/trace2/tr2_sysenv.c
> +++ b/trace2/tr2_sysenv.c
> @@ -74,7 +74,9 @@ static int tr2_sysenv_cb(const char *key, const char *value,
> if (!value)
> return config_error_nonbool(key);
> free(tr2_sysenv_settings[k].value);
> - tr2_sysenv_settings[k].value = xstrdup(value);
> + tr2_sysenv_settings[k].value = strdup(value);
> + if (!tr2_sysenv_settings[k].value)
> + return -1;
I'm not sure if this matters, but I think the call sequence from
config.c to this function is:
read_very_early_config ->
config_with_options ->
git_config_from_file_with_options ->
do_config_from_file ->
do_config_from ->
git_parse_source ->
get_value ->
git_config_include ->
tr2_sysenv_cb
and the -1 unwinds back to git_parse_source, which breaks, formats an
error message, and calls die:
error_msg = xstrfmt(_("bad config line %d in file %s")...)
die("%s", error_msg)
Am I reading this right? If so, the -1 actually triggers a die as
well -- unless the allocation in xstrfmt manages to kill it first.
This isn't a regression (the old xstrdup() also died) and the die
isn't inside the trace functions, but the commit message might read as
promising more than it delivers. |
||
| #define xsnprintf(...) BANNED(xsnprintf) | ||
|
|
||
| #undef xstrdup | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elijah Newren wrote on the Git mailing list (how to reply to this email): On Tue, Aug 25, 2026 at 11:59 AM Derrick Stolee via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
[...]
>+ const char *redact = ":<REDACTED>";
>+ char *redacted;
[...]
> + memcpy(redacted, arg, prefix_len);
> + memcpy(redacted + prefix_len, redact, redact_len - 1);
Only copy redact_len - 1 bytes? So only ":<REDACTED" without the
trailing ">" ? Why?
> + memcpy(redacted + prefix_len + redact_len - 1, p + at,
> + suffix_len + 1);
> + return redacted;
> }
>There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Junio C Hamano wrote on the Git mailing list (how to reply to this email): Elijah Newren <newren@gmail.com> writes:
> On Tue, Aug 25, 2026 at 11:59 AM Derrick Stolee via GitGitGadget
> <gitgitgadget@gmail.com> wrote:
>>
> [...]
>>+ const char *redact = ":<REDACTED>";
>>+ char *redacted;
> [...]
>> + memcpy(redacted, arg, prefix_len);
>> + memcpy(redacted + prefix_len, redact, redact_len - 1);
>
> Only copy redact_len - 1 bytes? So only ":<REDACTED" without the
> trailing ">" ? Why?
Yeah, if it were (redact_len + 1) it would have worked better, perhaps?
>
>
>> + memcpy(redacted + prefix_len + redact_len - 1, p + at,
>> + suffix_len + 1);
>> + return redacted;
>> }
>> |
||
| #define xstrdup(str) BANNED(xstrdup) | ||
|
|
||
| #undef xcalloc | ||
| #define xcalloc(nmemb, size) BANNED(xcalloc) | ||
|
|
||
| #undef xstrfmt | ||
| #define xstrfmt(...) BANNED(xstrfmt) | ||
|
|
||
| #undef ALLOC_ARRAY | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elijah Newren wrote on the Git mailing list (how to reply to this email): On Tue, Aug 25, 2026 at 11:57 AM Derrick Stolee via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> From: Derrick Stolee <stolee@gmail.com>
>
> The ALLOC_GROW() helper can call die() on a failed memory allocation.
> We need to remove this from the trace2 API code to prevent a recursive
> die() handler.
>
> This helper is used to track the nested region stack. Use a new
> skipped_regions member to track how many times a region was entered
> without being added to the stack, and decrease that amount as we leave
> each region. This allows us to avoid a failure and instead stop
> deepening the stack, giving as much nesting behavior as possible without
> failing the entire process.
>
> Signed-off-by: Derrick Stolee <stolee@gmail.com>
Checking out this commit and running
GIT_TRACE2_PERF=1 ./bin-wrappers/git status
dies with
no open regions in thread 'main'
Seems to be fixed by 7/7, though. Maybe a bad splitting? |
||
| #define ALLOC_ARRAY(x, alloc) BANNED(ALLOC_ARRAY) | ||
|
|
||
| #undef ALLOC_GROW | ||
| #define ALLOC_GROW(x, nr, alloc) BANNED(ALLOC_GROW) | ||
|
|
||
| #endif /* BANNED_DIE_H */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,47 +1,67 @@ | ||
| #include "git-compat-util.h" | ||
| #include "tr2_tbuf.h" | ||
| #include "banned-die.h" | ||
|
|
||
| void tr2_tbuf_local_time(struct tr2_tbuf *tb) | ||
| { | ||
| struct timeval tv; | ||
| struct tm tm; | ||
| struct timeval tv = { 0 }; | ||
| struct tm tm = { 0 }; | ||
| time_t secs; | ||
| int len; | ||
|
|
||
| gettimeofday(&tv, NULL); | ||
| secs = tv.tv_sec; | ||
| localtime_r(&secs, &tm); | ||
|
|
||
| xsnprintf(tb->buf, sizeof(tb->buf), "%02d:%02d:%02d.%06ld", tm.tm_hour, | ||
| tm.tm_min, tm.tm_sec, (long)tv.tv_usec); | ||
| len = snprintf(tb->buf, sizeof(tb->buf), "%02d:%02d:%02d.%06ld", | ||
| tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec); | ||
|
|
||
| if (len < 0 || (size_t)len >= sizeof(tb->buf)) { | ||
| const char *blank = "00:00:00.000000"; | ||
| strlcpy(tb->buf, blank, sizeof(tb->buf)); | ||
| } | ||
| } | ||
|
|
||
| void tr2_tbuf_utc_datetime_extended(struct tr2_tbuf *tb) | ||
| { | ||
| struct timeval tv; | ||
| struct tm tm; | ||
| struct timeval tv = { 0 }; | ||
| struct tm tm = { 0 }; | ||
| time_t secs; | ||
| int len; | ||
|
|
||
| gettimeofday(&tv, NULL); | ||
| secs = tv.tv_sec; | ||
| gmtime_r(&secs, &tm); | ||
|
|
||
| xsnprintf(tb->buf, sizeof(tb->buf), | ||
| "%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ", tm.tm_year + 1900, | ||
| tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
| (long)tv.tv_usec); | ||
| len = snprintf(tb->buf, sizeof(tb->buf), | ||
| "%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ", | ||
| tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
| tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec); | ||
|
|
||
| if (len < 0 || (size_t)len >= sizeof(tb->buf)) { | ||
| const char *blank = "1900-00-00T00:00:00.000000Z"; | ||
| strlcpy(tb->buf, blank, sizeof(tb->buf)); | ||
| } | ||
| } | ||
|
|
||
| void tr2_tbuf_utc_datetime(struct tr2_tbuf *tb) | ||
| { | ||
| struct timeval tv; | ||
| struct tm tm; | ||
| struct timeval tv = { 0 }; | ||
| struct tm tm = { 0 }; | ||
| time_t secs; | ||
| int len; | ||
|
|
||
| gettimeofday(&tv, NULL); | ||
| secs = tv.tv_sec; | ||
| gmtime_r(&secs, &tm); | ||
|
|
||
| xsnprintf(tb->buf, sizeof(tb->buf), "%4d%02d%02dT%02d%02d%02d.%06ldZ", | ||
| tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, | ||
| tm.tm_min, tm.tm_sec, (long)tv.tv_usec); | ||
| len = snprintf(tb->buf, sizeof(tb->buf), | ||
| "%4d%02d%02dT%02d%02d%02d.%06ldZ", | ||
| tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
| tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec); | ||
|
|
||
| if (len < 0 || (size_t)len >= sizeof(tb->buf)) { | ||
| const char *blank = "19000000T000000.000000Z"; | ||
| strlcpy(tb->buf, blank, sizeof(tb->buf)); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Junio C Hamano wrote on the Git mailing list (how to reply to this email):