Skip to content

Fix dangling pointer bug in AutoFDOProfileReader::ReadNameTable#263

Merged
snehasish merged 2 commits intogoogle:masterfrom
dc03-work:fix-dangling-pointer
Mar 11, 2026
Merged

Fix dangling pointer bug in AutoFDOProfileReader::ReadNameTable#263
snehasish merged 2 commits intogoogle:masterfrom
dc03-work:fix-dangling-pointer

Conversation

@dc03-work
Copy link
Contributor

The gcov_read_string function (https://github.com/google/autofdo/blob/master/gcov.cc#L226) returns a raw pointer to an internal buffer that can be realloc'd if it is too small (https://github.com/google/autofdo/blob/master/gcov.cc#L182-L184):

static inline void gcov_allocate(unsigned byte_length) {
  ...
  gcov_var.buffer =
      static_cast<char *>(realloc(gcov_var.buffer, new_byte_size));
}

...

static inline const char *gcov_read_bytes(unsigned bytes) {
  const char *result;
  unsigned excess_bytes = gcov_var.byte_length - gcov_var.byte_offset;

  ...
  if (excess_bytes < bytes) {
    ...
    if (gcov_var.byte_length + bytes > gcov_var.byte_alloc) {
      gcov_allocate(gcov_var.byte_length + bytes);
    }
    ...
  }
  ...
}

const char * gcov_read_string(void) {
  ...
  if (absl::GetFlag(FLAGS_gcov_version) >= 2) {
    return gcov_read_bytes (length);
  }
  ...
}

This means that the pointer that is returned can be invalidated by the very next read from the buffer, as seemed to be happening here. When I was stepping through this in a debugger, the string that was read magically got turned into an empty string after the next read.

The gcov_read_string function (https://github.com/google/autofdo/blob/master/gcov.cc#L226)
returns a raw pointer to an internal buffer that can be realloc'd if it is too
small (https://github.com/google/autofdo/blob/master/gcov.cc#L182-L184):

```cpp
static inline void gcov_allocate(unsigned byte_length) {
  ...
  gcov_var.buffer =
      static_cast<char *>(realloc(gcov_var.buffer, new_byte_size));
}

...

static inline const char *gcov_read_bytes(unsigned bytes) {
  const char *result;
  unsigned excess_bytes = gcov_var.byte_length - gcov_var.byte_offset;

  ...
  if (excess_bytes < bytes) {
    ...
    if (gcov_var.byte_length + bytes > gcov_var.byte_alloc) {
      gcov_allocate(gcov_var.byte_length + bytes);
    }
    ...
  }
  ...
}

const char * gcov_read_string(void) {
  ...
  if (absl::GetFlag(FLAGS_gcov_version) >= 2) {
    return gcov_read_bytes (length);
  }
  ...
}
```

This means that the pointer that is returned can be invalidated by the very next
read from the buffer, as seemed to be happening here. When I was stepping through
this in a debugger, the string that was read magically got turned into an empty
string after the next read.
@dc03-work
Copy link
Contributor Author

Ping @snehasish

symbol_map.h Outdated

static std::string Name(const char *name) {
return (name && strlen(name) > 0) ? name : "noname";
CHECK(strlen(name) > 0 && "Empty string should never occur in profile!");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Calling strlen on null is undefined behaviour. This check doesn't seem to make sense if you return "noname" anyway? Can you refactor this to drop "noname"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

uint32_t name_vector_size = gcov_read_unsigned();
for (uint32_t i = 0; i < name_vector_size; i++) {
const char *name = gcov_read_string();
const char *name = strdup(gcov_read_string());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we are leaking memory here with strdup since the emplace call below copies the stirng content into names? Maybe just use std::string name(gcov_read_string()); here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@dc03-work
Copy link
Contributor Author

Ping @snehasish ?

@snehasish
Copy link
Collaborator

Hmm, the CI failure seems unrelated though I would like to have it fixed before we merge this. @dhoekwater Could you take a look?

@dc03-work
Copy link
Contributor Author

Could you try re-running the CI? Looks like a spurious apt failure.

Copy link
Collaborator

@snehasish snehasish left a comment

Choose a reason for hiding this comment

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

lgtm

@snehasish
Copy link
Collaborator

Could you try re-running the CI? Looks like a spurious apt failure.

Thanks for the nudge, I should have looked more closely.

@snehasish snehasish merged commit da0cc63 into google:master Mar 11, 2026
3 of 4 checks passed
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