Fix use-after-free of DataStorage metrics page address label#390
Open
vporoshok wants to merge 1 commit into
Open
Fix use-after-free of DataStorage metrics page address label#390vporoshok wants to merge 1 commit into
vporoshok wants to merge 1 commit into
Conversation
Two related issues caused intermittent invalid (non-UTF-8) values for the `address` label of `prompp_data_storage_*` metrics during self-scrape: 1. The `address` label value was a non-owning view (Go::String) into a std::string stored inside DataStorage. On DataStorage destruction the page was only detached, but the backing string was freed immediately, so a concurrent scrape holding the page read freed memory. Move ownership of the address string into the Metrics page so its lifetime matches the page (reclaimed only by remove_unused_pages()). 2. Metric scrapes were not serialized. client_golang does not serialize Gather/Collect, so two concurrent scrapes could race: one deletes (via remove_unused_pages) a page another is still iterating. Add a mutex around the whole CppMetrics iteration to guarantee a single reader. Add a regression test asserting the address label stays valid after the owning DataStorage is destroyed. Co-authored-by: Cursor <cursoragent@cursor.com>
gshigin
approved these changes
Jun 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes intermittent invalid (non-UTF-8) values for the
addresslabel ofprompp_data_storage_*metrics, which made prompp's self-scrape fail to parse its own metrics (invalid utf8 in label_value ... prompp_data_storage_asc_int_count{address=...}).Two related root causes:
Dangling label view (use-after-free). The
addresslabel value was a non-owningGo::Stringview into astd::stringstored insideDataStorage. OnDataStoragedestruction the metrics page was only detached (deferred removal), but the backing string was freed immediately in the destructor. A concurrent scrape that already advanced onto the page would read freed/reused memory — hence the rare garbage bytes. Ownership of the address string is moved into theMetricspage, so its lifetime matches the page and it is reclaimed only byremove_unused_pages().Unserialized scrapes.
client_golangdoes not serializeGather/Collect, so two concurrent scrapes could race:prompp_metrics_iterator_ctorcallsremove_unused_pages()(which physically deletes detached pages), so one scrape coulddeletea page another scrape is still iterating. A mutex now serializes the wholeCppMetricsiteration, guaranteeing the single-reader invariant the detach/remove design relies on.Changes
pp/series_data/metrics.h—Metricspage ownsaddress_label_(moved in); metrics built from alabel_set()helper viewing the page-owned string.pp/series_data/data_storage.h— drop theaddress_label_member fromDataStorage; pass the address string to the page at construction.pp/go/cppbridge/metrics.go— package-levelsync.Mutexheld for the fullCppMetricsiteration.pp/series_data/tests/metrics_tests.cpp— regression test asserting theaddresslabel stays valid after the owningDataStorageis destroyed.Test plan
make build-entrypoint(ARM devcontainer)//:metrics_test,//:series_data_testpass--asan=true./pp/go/cppbridgemetrics tests passgofmtcleanMade with Cursor