Skip to content
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

GCC (mis)catches a use-after-free condition in parse.c #215

Open
khorben opened this issue May 23, 2023 · 1 comment
Open

GCC (mis)catches a use-after-free condition in parse.c #215

khorben opened this issue May 23, 2023 · 1 comment

Comments

@khorben
Copy link
Contributor

khorben commented May 23, 2023

When compiling with -Wuse-after-free=2, GCC catches the following problem in parse.c from the 1.8.3 release:

--- parse.o ---
contrib/ldns/parse.c: In function 'ldns_fget_token_l_st':
contrib/ldns/parse.c:151:57: error: pointer may be used after 'realloc' [-Werror=use-after-free]
  151 |                                         t = *token + (t - old_token);
      |                                                      ~~~^~~~~~~~~~~~
In file included from contrib/ldns/ldns/ldns.h:95,
                 from contrib/ldns/parse.c:11:
contrib/ldns/ldns/util.h:58:19: note: call to 'realloc' here
   58 |         ((type *) realloc((ptr), (count) * sizeof(type)))
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
contrib/ldns/parse.c:144:42: note: in expansion of macro 'LDNS_XREALLOC'
  144 |                                 *token = LDNS_XREALLOC(*token, char, *limit + 1);
      |                                          ^~~~~~~~~~~~~
contrib/ldns/parse.c:185:49: error: pointer 'old_token' may be used after 'realloc' [-Werror=use-after-free]
  185 |                                 t = *token + (t - old_token);
      |                                              ~~~^~~~~~~~~~~~
contrib/ldns/ldns/util.h:58:19: note: call to 'realloc' here
   58 |         ((type *) realloc((ptr), (count) * sizeof(type)))
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
contrib/ldns/parse.c:178:34: note: in expansion of macro 'LDNS_XREALLOC'
  178 |                         *token = LDNS_XREALLOC(*token, char, *limit + 1);
      |                                  ^~~~~~~~~~~~~

After reading it, I believe the corresponding code is harmless, since it never actually dereferences old_token. It is however very inelegant in the way it performs pointer arithmetic to keep track of t, and should probably be modified to use an array index instead.

@jrtc27
Copy link

jrtc27 commented May 24, 2023

The warning is technically correct. However, this is a common pattern, and in practice I'm not aware of this being a problem with current toolchains. What is definitely a problem is doing something along the lines of:

q = realloc(p, ...);
foo = foo + (q - p);

because that doesn't give foo the right provenance, and that's something that the recently-added _FORTIFY_SOURCE=3 in GCC supposedly catches, as does CHERI. But the code isn't doing that, the provenance is correct, the issue is just that, strictly, the value of the pointer given to realloc is now indeterminate^1, which isn't particularly helpful, nor is it really necessary to be specified like that. In this case, one could trivially address the issue by hoisting the t - old_token calculation before the realloc (and remove the now-obsolete old_token), and let the compiler decide to sink it back to its use, which it will surely do. I would expect identical code to be generated.

^1 C99 6.2.4p2: "The value of a pointer becomes indeterminate when the object it points to reaches the end of its lifetime."

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

No branches or pull requests

2 participants