microsoft / microsoft/mimalloc

AddressSanitizer: global buffer overflow in `mi_stat_update`

Open
#1,124 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

stale
Dominant language
C
Stars
13.4k
Forks
1.2k
Avg merge
4d 45m
Merged PRs (30d)
13

Description

Running with version 2.2.4 under ASan produces the following error when releasing a heap:

=================================================================
==5940==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7ff6228aa360 at pc 0x7ff6222cf09a bp 0x00e060b4baf0 sp 0x00e060b4baf8
READ of size 8 at 0x7ff6228aa360 thread T0
    #0 0x7ff6222cf099 in mi_stat_update D:\projects\solvespace\extlib\mimalloc\src\stats.c:41
    #1 0x7ff6222cec12 in _mi_stat_decrease(struct mi_stat_count_s *, unsigned __int64) D:\projects\solvespace\extlib\mimalloc\src\stats.c:61
    #2 0x7ff6222c14b9 in mi_segment_page_clear D:\projects\solvespace\extlib\mimalloc\src\segment.c:1027
    #3 0x7ff6222b7224 in _mi_segment_page_free(struct mi_page_s *, bool, struct mi_segments_tld_s *) D:\projects\solvespace\extlib\mimalloc\src\segment.c:1059
    #4 0x7ff62229e2e1 in _mi_heap_page_destroy D:\projects\solvespace\extlib\mimalloc\src\heap.c:365
    #5 0x7ff62229d5c0 in mi_heap_visit_pages D:\projects\solvespace\extlib\mimalloc\src\heap.c:46
    #6 0x7ff62229ae9f in _mi_heap_destroy_pages(struct mi_heap_s *) D:\projects\solvespace\extlib\mimalloc\src\heap.c:371
    #7 0x7ff622299f85 in mi_heap_destroy D:\projects\solvespace\extlib\mimalloc\src\heap.c:405
    #8 0x7ff6216c0162 in SolveSpace::Platform::MimallocHeap::~MimallocHeap(void) D:\projects\solvespace\src\platform\platformbase.cpp:74
    #9 0x7ff6216bfc84 in SolveSpace::Platform::FreeAllTemporary(void) D:\projects\solvespace\src\platform\platformbase.cpp:93
    #10 0x7ff6216570f0 in SolveSpace::SolveSpaceUI::SolveGroup(class SolveSpace::hGroup, bool) D:\projects\solvespace\src\generate.cpp:567
    #11 0x7ff62165713a in SolveSpace::SolveSpaceUI::SolveGroupAndReport(class SolveSpace::hGroup, bool) D:\projects\solvespace\src\generate.cpp:512
    #12 0x7ff621656337 in SolveSpace::SolveSpaceUI::GenerateAll(enum SolveSpace::SolveSpaceUI::Generate, bool, bool) D:\projects\solvespace\src\generate.cpp:291
    #13 0x7ff621655808 in SolveSpace::SolveSpaceUI::GenerateAll(enum SolveSpace::SolveSpaceUI::Generate, bool, bool) D:\projects\solvespace\src\generate.cpp:215
    #14 0x7ff62146b897 in SolveSpace::SolveSpaceUI::AfterNewFile(void) D:\projects\solvespace\src\solvespace.cpp:544
    #15 0x7ff6213b93ef in SolveSpace::Test::Helper::CheckLoad(char const *, int, char const *) D:\projects\solvespace\test\harness.cpp:217
    #16 0x7ff621448e46 in Test_other_roundtrip D:\projects\solvespace\test\constraint\equal_angle\test.cpp:20
    #17 0x7ff62142f9f3 in std::invoke<void (__cdecl *&)(class SolveSpace::Test::Helper *), class SolveSpace::Test::Helper *>(void (__cdecl *&)(class SolveSpace::Test::Helper *), class SolveSpace::Test::Helper *&&) C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\type_traits:1680
    #18 0x7ff62142fab8 in std::_Func_impl_no_alloc<void (__cdecl *)(class SolveSpace::Test::Helper *), void, class SolveSpace::Test::Helper *>::_Do_call(class SolveSpace::Test::Helper *&&) C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\functional:880
    #19 0x7ff6213fa9f1 in std::_Func_class<void, class SolveSpace::Test::Helper *>::operator()(class SolveSpace::Test::Helper *) const C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.44.35207\include\functional:926
    #20 0x7ff6213bf24c in main D:\projects\solvespace\test\harness.cpp:381
    #21 0x7ff622374c68 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #22 0x7ff622374bb1 in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #23 0x7ff622374a6d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
    #24 0x7ff622374cdd in mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
    #25 0x7ffd0bcb7373  (C:\Windows\System32\KERNEL32.DLL+0x180017373)
    #26 0x7ffd0d2dcc90  (C:\Windows\SYSTEM32\ntdll.dll+0x18004cc90)

0x7ff6228aa360 is located 16 bytes after global variable 'tld_main' defined in 'init.c:153:36' (0x7ff6228a8f40) of size 5136
SUMMARY: AddressSanitizer: global-buffer-overflow D:\projects\solvespace\extlib\mimalloc\src\stats.c:41 in mi_stat_update
Shadow bytes around the buggy address:
  0x7ff6228aa080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6228aa100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6228aa180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6228aa200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6228aa280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7ff6228aa300: 00 00 00 00 00 00 00 00 00 00 f9 f9[f9]f9 f9 f9
  0x7ff6228aa380: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x7ff6228aa400: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x7ff6228aa480: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x7ff6228aa500: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
  0x7ff6228aa580: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
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
==5940==ABORTING

This is caused by the fact that _mi_page_bin(page) returns MI_BIN_FULL (defined in mimalloc/types.h, and evaluating to 74) in mi_segment_page_clear(), while mi_stats_t::page_bins can only hold MI_BIN_HUGE+1 (73+1) elements, causing an off-by-one overflow. This likely requires page_bins to grow to MI_BIN_FULL+1, but I don't know if this is the right fix or not, and if the malloc_bins member should also grow accordingly.

This doesn't happen with 2.2.3, and is likely caused by 08c33768a5344e43a1ba95b88c3adcbb6a5c3498.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with mi_stat_update in extlib/mimalloc/src/stats.c and compare _mi_page_bin handling in mi_segment_page_clear from segment.c against MI_BIN_FULL in include/mimalloc/types.h. Inspect page_bins and malloc_bins in include/mimalloc-stats.h, then reproduce the 2.2.4 case under ASan and compare with 2.2.3. Done means the reported global-buffer-overflow no longer occurs and the statistics arrays remain correctly bounded.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.