Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-124193

[REG 5.15 - 6.x] QList::removeAll() causes ASan's stack-use-after-scope in some cases

    XMLWordPrintable

Details

    • Bug
    • Resolution: Out of scope
    • P2: Important
    • None
    • 6.5.3, 6.6.3, 6.7.0
    • None
    • Microsoft Visual Studio Professional 2022 (64-bit) Version 17.9.5
      The CXX compiler identification is MSVC 19.39.33523.0
    • Windows

    Description

      QList::removeAll() causes ASan's stack-use-after-scope in some cases with MSVC.

      ==36660==ERROR: AddressSanitizer: stack-use-after-scope on address 0x006c41effa0
      0 at pc 0x7ff6cd95396e bp 0x006c41eff600 sp 0x006c41eff608
      READ of size 4 at 0x006c41effa00 thread T0
          #0 0x7ff6cd95396d in Base::operator==(struct Base const &) const C:\Users\Vl
      adimir\Documents\My Qt Projects\removeAll_issue\main.cpp:8
          #1 0x7ff6cd951575 in ??$?R$$CBUDerived@@@<lambda_1>@?1???$sequential_erase@V
      ?$QList@UDerived@@@@UDerived@@@QtPrivate@@YA?A_PAEAV?$QList@UDerived@@@@AEBUDeri
      ved@@@Z@QEBA?A_P1@Z E:\Qt5\qtbase\src\corelib\tools\qcontainertools_impl.h:371  
          #2 0x7ff6cd951d4f in ??$find_if@Vconst_iterator@?$QList@UDerived@@@@V<lambda
      _1>@?1???$sequential_erase@V?$QList@UDerived@@@@UDerived@@@QtPrivate@@YA?A_PAEAV
      2@AEBUDerived@@@Z@@std@@YA?AVconst_iterator@?$QList@UDerived@@@@V12@V12@V<lambda
      _1>@?1???$sequential_erase@V?$QList@UDerived@@@@UDerived@@@QtPrivate@@YA?A_PAEAV
      2@AEBUDerived@@@Z@@Z D:\Program Files\Microsoft Visual Studio\2022\Professional\
      VC\Tools\MSVC\14.39.33519\include\xutility:6278
          #3 0x7ff6cd95260a in ??$sequential_erase_if@V?$QList@UDerived@@@@V<lambda_1>
      @?1???$sequential_erase@V?$QList@UDerived@@@@UDerived@@@QtPrivate@@YA?A_PAEAV1@A
      EBUDerived@@@Z@@QtPrivate@@YA?A_PAEAV?$QList@UDerived@@@@AEAV<lambda_1>@?1???$se
      quential_erase@V?$QList@UDerived@@@@UDerived@@@0@YA?A_P0AEBUDerived@@@Z@@Z E:\Qt
      5\qtbase\src\corelib\tools\qcontainertools_impl.h:340
          #4 0x7ff6cd952458 in ??$sequential_erase@V?$QList@UDerived@@@@UDerived@@@QtP
      rivate@@YA?A_PAEAV?$QList@UDerived@@@@AEBUDerived@@@Z E:\Qt5\qtbase\src\corelib\
      tools\qcontainertools_impl.h:372
          #5 0x7ff6cd952b81 in ??$sequential_erase_with_copy@V?$QList@UDerived@@@@UDer
      ived@@@QtPrivate@@YA?A_PAEAV?$QList@UDerived@@@@AEBUDerived@@@Z E:\Qt5\qtbase\sr
      c\corelib\tools\qcontainertools_impl.h:380
          #6 0x7ff6cd95239c in QList<struct Derived>::removeAll<struct Derived>(struct
       Derived const &) E:\Qt5\qtbase\src\corelib\tools\qlist.h:594
          #7 0x7ff6cd951252 in main C:\Users\Vladimir\Documents\My Qt Projects\removeA
      ll_issue\main.cpp:24
          #8 0x7ff6cd959b68 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\sr
      c\startup\exe_common.inl:78
          #9 0x7ff6cd959abd in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\v
      cstartup\src\startup\exe_common.inl:288
          #10 0x7ff6cd95997d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcst
      artup\src\startup\exe_common.inl:330
          #11 0x7ff6cd959bdd in mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartu
      p\src\startup\exe_main.cpp:16
          #12 0x7ffedbe67343  (C:\WINDOWS\System32\KERNEL32.DLL+0x180017343)
      Address 0x006c41effa00 is located in stack of thread T0 at offset 32 in frame   
          #0 0x7ff6cd9529ff in ??$sequential_erase_with_copy@V?$QList@UDerived@@@@UDer
      ived@@@QtPrivate@@YA?A_PAEAV?$QList@UDerived@@@@AEBUDerived@@@Z E:\Qt5\qtbase\sr
      c\corelib\tools\qcontainertools_impl.h:377
      
        This frame has 1 object(s):
          [32, 36) 'compiler temporary' <== Memory access at offset 32 is inside this 
      variable
      HINT: this may be a false positive if your program uses some custom stack unwind
       mechanism, swapcontext or vfork
            (longjmp, SEH and C++ exceptions *are* supported)
      SUMMARY: AddressSanitizer: stack-use-after-scope C:\Users\Vladimir\Documents\My 
      Qt Projects\removeAll_issue\main.cpp:8 in Base::operator==(struct Base const &) 
      const
      Shadow bytes around the buggy address:
        0x020b1285fef0: 00 00 00 00 00 00 f1 f1 f1 f1 00 f2 00 f2 00 f2
        0x020b1285ff00: 00 f2 f8 f2 00 f2 00 f2 f8 f2 f8 f2 f8 f3 f3 f3
        0x020b1285ff10: f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
        0x020b1285ff20: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 f3 f3 f3
        0x020b1285ff30: f3 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
      =>0x020b1285ff40:[f8]f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00
        0x020b1285ff50: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
        0x020b1285ff60: 00 00 00 f2 f2 f2 f2 f8 f2 f8 f8 f2 f2 f2 f2 04
        0x020b1285ff70: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
        0x020b1285ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
        0x020b1285ff90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      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
      ==36660==ABORTING
      

      Reproducer:

      #include <QList>
      
      struct Base
      {
          explicit Base(int v) : value(v) {}
          bool operator == (const Base &other) const
          {
              return value == other.value;
          }
      
          int value = 0;
      };
      
      struct Derived : public Base
      {
          explicit Derived(int v) : Base(v) {}
      };
      
      int main()
      {
          QList<Derived> list { Derived(0), Derived(1) };
      
          Derived d(0);
          list.removeAll(d); // <-- AddressSanitizer: stack-use-after-scope
          //list.removeIf([d] (const auto &v) { return v == d; }); // <-- it's OK
      
          return 0;
      }
      

      Here is removeAll_issue.zipwith enabled Address Sanitizer in CMakeList.txt

      if (MSVC)
          add_compile_options(/fsanitize=address)
      else()
          add_compile_options(-fsanitize=address -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls)
          add_link_options(-fsanitize=address)
      endif(MSVC)
      

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              thiago Thiago Macieira
              studiosus Vladimir Belyavsky
              Votes:
              2 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes