Skip to content

Commit aaf45d7

Browse files
Abbondanzofacebook-github-bot
authored andcommitted
Fix crash in PerformanceEntrySorter comparator (#56388)
Summary: Fixed a SIGSEGV crash in the Performance API that occurred when sorting performance entries. The crash was caused by the PerformanceEntrySorter comparator missing the const qualifier on its operator() method. The PerformanceEntrySorter::operator() was not marked as const, which violates the requirements for comparators used with std::stable_sort. This caused undefined behavior and crashes on Android when sorting performance entries. Added the const qualifier to PerformanceEntrySorter::operator()() to ensure it's properly const-qualified for use with STL sorting algorithms. Changelog: [General][Fixed] - Fix crash in Performance API when sorting entries Reviewed By: rubennorte Differential Revision: D98674156
1 parent 0cb9c1b commit aaf45d7

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ using PerformanceEntry = std::variant<
8080
PerformanceResourceTiming>;
8181

8282
struct PerformanceEntrySorter {
83-
bool operator()(const PerformanceEntry &lhs, const PerformanceEntry &rhs)
83+
bool operator()(const PerformanceEntry &lhs, const PerformanceEntry &rhs) const
8484
{
8585
return std::visit(
8686
[](const auto &left, const auto &right) {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <gtest/gtest.h>
9+
10+
#include <algorithm>
11+
#include <type_traits>
12+
#include <vector>
13+
14+
#include "../PerformanceEntry.h"
15+
16+
using namespace facebook::react;
17+
18+
// Verify that PerformanceEntrySorter::operator() is const-qualified.
19+
// Without const, std::stable_sort may fail to compile on toolchains where
20+
// the comparator is passed through a const-qualified code path (e.g.
21+
// libc++ __insertion_sort on NDK 19.x), causing SIGSEGV at runtime on
22+
// others. See T263807207.
23+
TEST(PerformanceEntry, SorterOperatorIsConst) {
24+
static_assert(
25+
std::is_invocable_v<
26+
const PerformanceEntrySorter,
27+
const PerformanceEntry&,
28+
const PerformanceEntry&>,
29+
"PerformanceEntrySorter::operator() must be const-qualified");
30+
}
31+
32+
TEST(PerformanceEntry, SortEntriesByStartTimeThenDuration) {
33+
auto t0 = HighResTimeStamp::now();
34+
auto t1 = t0 + HighResDuration::fromMilliseconds(1);
35+
auto t2 = t0 + HighResDuration::fromMilliseconds(2);
36+
37+
std::vector<PerformanceEntry> entries = {
38+
PerformanceMark{{.name = "c", .startTime = t2}},
39+
PerformanceMark{{.name = "a", .startTime = t0}},
40+
PerformanceMeasure{
41+
{.name = "b",
42+
.startTime = t0,
43+
.duration = HighResDuration::fromMilliseconds(5)}},
44+
PerformanceMark{
45+
{.name = "d", .startTime = t1, .duration = HighResDuration::zero()}},
46+
};
47+
48+
std::stable_sort(entries.begin(), entries.end(), PerformanceEntrySorter{});
49+
50+
// Entries with same startTime are ordered by duration (ascending).
51+
// "a" (t0, dur=0) < "b" (t0, dur=5) < "d" (t1, dur=0) < "c" (t2, dur=0)
52+
ASSERT_EQ(4, entries.size());
53+
54+
auto getName = [](const PerformanceEntry& e) {
55+
return std::visit([](const auto& x) { return x.name; }, e);
56+
};
57+
58+
EXPECT_EQ("a", getName(entries[0]));
59+
EXPECT_EQ("b", getName(entries[1]));
60+
EXPECT_EQ("d", getName(entries[2]));
61+
EXPECT_EQ("c", getName(entries[3]));
62+
}

0 commit comments

Comments
 (0)