Skip to content

Commit 5585e4e

Browse files
committed
fix(symbols): skip layout parsing for large symbols in read stream paths
Signed-off-by: VIFEX <vifextech@foxmail.com>
1 parent 8d60928 commit 5585e4e

2 files changed

Lines changed: 93 additions & 12 deletions

File tree

Tools/WebServer/app/routes/symbols.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -924,9 +924,15 @@ def api_read_symbol_from_device():
924924
struct_layout = None
925925
gdb_values = None
926926
if not is_pointer:
927-
struct_layout = _get_struct_layout_cached(sym_name)
928-
if struct_layout:
929-
gdb_values = _decode_struct_values(struct_layout, hex_data)
927+
if size > MAX_LAYOUT_ANALYSIS_SIZE:
928+
logger.warning(
929+
f"[read] skip struct layout for large symbol '{sym_name}' "
930+
f"(size={size} > {MAX_LAYOUT_ANALYSIS_SIZE})"
931+
)
932+
else:
933+
struct_layout = _get_struct_layout_cached(sym_name)
934+
if struct_layout:
935+
gdb_values = _decode_struct_values(struct_layout, hex_data)
930936

931937
resp = {
932938
"success": True,
@@ -1125,9 +1131,15 @@ def do_read_wrapper():
11251131
struct_layout = None
11261132
gdb_values = None
11271133
if not is_pointer:
1128-
struct_layout = _get_struct_layout_cached(sym_name)
1129-
if struct_layout:
1130-
gdb_values = _decode_struct_values(struct_layout, hex_data)
1134+
if size > MAX_LAYOUT_ANALYSIS_SIZE:
1135+
logger.warning(
1136+
f"[read/stream] skip struct layout for large symbol '{sym_name}' "
1137+
f"(size={size} > {MAX_LAYOUT_ANALYSIS_SIZE})"
1138+
)
1139+
else:
1140+
struct_layout = _get_struct_layout_cached(sym_name)
1141+
if struct_layout:
1142+
gdb_values = _decode_struct_values(struct_layout, hex_data)
11311143

11321144
resp = {
11331145
"type": "result",

Tools/WebServer/tests/test_symbols_routes.py

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -658,9 +658,9 @@ def test_value_large_symbol_skips_layout(self, _mock_gdb_avail):
658658
)
659659
state.gdb_session = mock_session
660660
state.symbols = {
661-
"__framebuffer_start__": {
662-
"addr": 0x2001E000,
663-
"size": 1789440,
661+
"test_buffer": {
662+
"addr": 0x20000000,
663+
"size": 10485760,
664664
"type": "variable",
665665
"section": ".bss",
666666
}
@@ -669,14 +669,14 @@ def test_value_large_symbol_skips_layout(self, _mock_gdb_avail):
669669
with tempfile.NamedTemporaryFile(suffix=".elf", delete=False) as f:
670670
state.device.elf_path = f.name
671671
try:
672-
response = self.client.get("/api/symbols/value?name=__framebuffer_start__")
672+
response = self.client.get("/api/symbols/value?name=test_buffer")
673673
data = response.get_json()
674674
self.assertTrue(data["success"])
675-
self.assertEqual(data["name"], "__framebuffer_start__")
675+
self.assertEqual(data["name"], "test_buffer")
676676
self.assertIsNone(data["struct_layout"])
677677
self.assertIsNone(data["gdb_values"])
678678
mock_session.read_symbol_value.assert_called_once_with(
679-
"__framebuffer_start__"
679+
"test_buffer"
680680
)
681681
mock_session.read_symbol_value_and_layout.assert_not_called()
682682
finally:
@@ -841,6 +841,38 @@ def test_read_failure(self, mock_get_fpb, mock_run_serial):
841841
finally:
842842
os.unlink(state.device.elf_path)
843843

844+
@patch("app.routes.symbols._get_struct_layout_cached")
845+
@patch("app.routes.symbols._run_serial_op", side_effect=lambda func, **kw: func())
846+
@patch("app.routes.symbols._get_fpb_inject")
847+
def test_read_large_symbol_skips_layout(
848+
self, mock_get_fpb, _mock_run_serial, mock_get_layout
849+
):
850+
mock_fpb = Mock()
851+
mock_fpb.read_memory.return_value = (b"\xaa" * 16, "Read 16 bytes OK")
852+
mock_get_fpb.return_value = mock_fpb
853+
state.symbols = {
854+
"test_buffer": {
855+
"addr": 0x20000000,
856+
"size": 10485760,
857+
"type": "variable",
858+
"section": ".bss",
859+
}
860+
}
861+
state.symbols_loaded = True
862+
with tempfile.NamedTemporaryFile(suffix=".elf", delete=False) as f:
863+
state.device.elf_path = f.name
864+
try:
865+
response = self.client.post(
866+
"/api/symbols/read", json={"name": "test_buffer"}
867+
)
868+
data = response.get_json()
869+
self.assertTrue(data["success"])
870+
self.assertIsNone(data["struct_layout"])
871+
self.assertIsNone(data["gdb_values"])
872+
mock_get_layout.assert_not_called()
873+
finally:
874+
os.unlink(state.device.elf_path)
875+
844876

845877
class TestWriteSymbolToDevice(SymbolRoutesBase):
846878
"""Test /api/symbols/write endpoint."""
@@ -1573,6 +1605,43 @@ def test_stream_read_failure(self, mock_lookup, mock_fpb_fn):
15731605
finally:
15741606
os.unlink(state.device.elf_path)
15751607

1608+
@patch("app.routes.symbols._get_struct_layout_cached")
1609+
@patch("app.routes.symbols._get_fpb_inject")
1610+
@patch("app.routes.symbols._lookup_symbol")
1611+
def test_stream_large_symbol_skips_layout(
1612+
self, mock_lookup, mock_fpb_fn, mock_get_layout
1613+
):
1614+
mock_lookup.return_value = {
1615+
"addr": 0x20000000,
1616+
"size": 10485760,
1617+
"type": "variable",
1618+
"is_pointer": False,
1619+
}
1620+
mock_fpb = Mock()
1621+
1622+
def fake_read(addr, size, progress_callback=None):
1623+
if progress_callback:
1624+
progress_callback(size, size)
1625+
return b"\x01" * 16, "OK"
1626+
1627+
mock_fpb.read_memory.side_effect = fake_read
1628+
mock_fpb_fn.return_value = mock_fpb
1629+
1630+
with tempfile.NamedTemporaryFile(suffix=".elf", delete=False) as f:
1631+
state.device.elf_path = f.name
1632+
try:
1633+
response = self.client.post(
1634+
"/api/symbols/read/stream", json={"name": "test_buffer"}
1635+
)
1636+
events = _parse_sse_events(response.get_data(as_text=True))
1637+
result_evt = next(e for e in events if e["type"] == "result")
1638+
self.assertTrue(result_evt["success"])
1639+
self.assertIsNone(result_evt["struct_layout"])
1640+
self.assertIsNone(result_evt["gdb_values"])
1641+
mock_get_layout.assert_not_called()
1642+
finally:
1643+
os.unlink(state.device.elf_path)
1644+
15761645
@patch("app.routes.symbols._get_fpb_inject")
15771646
@patch("app.routes.symbols._lookup_symbol")
15781647
def test_stream_worker_timeout(self, mock_lookup, mock_fpb_fn):

0 commit comments

Comments
 (0)