The following code snippet very roughly resembles what happens in the libsecp test harness and illustrates the issue:
0/* in the tests we have access to a global context */
1static secp256k1_context *ctx = NULL;
2
3void test_foo() {
4 int ecount;
5 context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
6 /* do some tests with ecount */
7}
8void test_bar() {
9 /* we don't set the counting_illegal_callback here because we don't want to test that here */
10 some_function(ctx);
11}
12void main() {
13 test_foo();
14 test_bar();
15}
The code is fine, until one day some_function(ctx)
results in the illegal callback being called.
Then we’d want the test to fail but instead what happens is that some stack region formerly known as ecount
is modified, which does not necessarily result in a crash.
One solution would be to never add the counting_illegal_callback
to the global context and instead create a local context for counting.