operator[] bei std::vector



  • Hallo,

    machen übliche Compiler - ich verwende gcc - im debug modus für den operator[]
    bei std::vector eigentlich einen Range-Test?

    Gruß,
    Newbie19



  • schau dir einfach den code an



  • VC ja



  • ja schrieb:

    VC ja

    Auch bei Release? Auch bei _SECUREL_SCL == 0?...



  • Kommt drauf an, was für einen Debugmodus Du meinst. Normalerweise bedeutet das, dass Optimierungen ausgeschaltet werden und Debuginformationen "-g" eingefügt werden, wohingegen im Releasemodus Optimierungen eingeschaltet werden und "-DNDEBUG" benutzt wird, welches u.a. auch assert s ausschaltet.

    Wenn Du das mit "Debugmodus" meinst, dann ist die Antwort nein. Es findet keine Bereichsprüfung statt.

    Es gibt aber noch extra einen Debugmodus für die Standardbibliothek. Diesen kannst Du mit -D_GLIBCXX_DEBUG aktivieren, wenn Du Dein Programm kompilierst. Dann werden insgesamt sehr sehr viele Überprüfungen gemacht -- siehe http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html. Auch operator[] testet dann die Indizes auf Gültigkeit. Wenn da etwas nicht passt, wird das Programm abgebrochen.

    Hier ein Beispiel:

    #include <iostream>
    #include <vector>
    
    void foo(std::vector<int> const& t)
    {
    	std::cout << t[3] << '\n';
    }
    
    int main()
    {
    	std::vector<int> t;
    	t.push_back(23);
    	t.push_back(42);
    	t.push_back(99);
    	try {
    		foo(t);
    	} catch (...) {
    		std::cout << "yay!\n";
    	}
    }
    

    Kompilieren und im Debugger laufen lassen:

    kk@home:/tmp$ g++ -D_GLIBCXX_DEBUG -g -otest test.cpp
    kk@home:/tmp$ gdb ./test 
    GNU gdb (GDB) 7.1-ubuntu
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i486-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /tmp/test...done.
    (gdb) run
    Starting program: /tmp/test 
    /usr/include/c++/4.4/debug/vector:272:error: attempt to subscript container 
        with out-of-bounds index 3, but container only holds 3 elements.
    
    Objects involved in the operation:
    sequence "this" @ 0x0xbffff3e4 {
      type = NSt7__debug6vectorIiSaIiEEE;
    }
    
    Program received signal SIGABRT, Aborted.
    0x0012d422 in __kernel_vsyscall ()
    (gdb) backtrace
    #0  0x0012d422 in __kernel_vsyscall ()
    #1  0x00293651 in *__GI_raise (sig=6)
        at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
    #2  0x00296a82 in *__GI_abort () at abort.c:92
    #3  0x00180f52 in __gnu_debug::_Error_formatter::_M_error() const ()
       from /usr/lib/libstdc++.so.6
    #4  0x080490c8 in std::__debug::vector<int, std::allocator<int> >::operator[] (
        this=0xbffff3e4, __n=3) at /usr/include/c++/4.4/debug/vector:272
    #5  0x08048c2d in foo (t=...) at test.cpp:6
    #6  0x08048d06 in main () at test.cpp:16
    (gdb)
    

    Du kannst Dich aber darauf einstellen, dass das Programm ohne Optimierungen und mit den ganzen Zusatzüberprüfungen sehr langsam läuft.

    kk



  • krümelkacker schrieb:

    Es gibt aber noch extra einen Debugmodus für die Standardbibliothek. Diesen kannst Du mit -D_GLIBCXX_DEBUG aktivieren, wenn Du Dein Programm kompilierst.

    Danke Krümelkacker!
    Genau so etwas meinte ich!



  • theta schrieb:

    ja schrieb:

    VC ja

    Auch bei _SECUREL_SCL == 0?...

    🙄



  • Naja, probier es doch aus?

    #include <cstdio>
    #include <vector>
    using namespace std;
    
    int main()
    {
    	vector<int> foo(5);
    	fill(foo.begin(), foo.end(), 1337);
    
    	for(vector<int>::size_type i = 0; i < 10; ++i)
    		printf("operator[] : %d , at() : %d\n", foo[i], foo.at(i));
    
    }
    

    Verwurstet der VC++ 2008 im Release Mode zu (Pseudo-Code)

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      int *v3; // eax@1
      unsigned int v4; // ebx@1
      int *v5; // esi@1
      int v6; // eax@1
      int v7; // ebx@1
      int v8; // ebp@1
      int v9; // esi@1
      int v10; // edi@1
      std::vector<int,std::allocator<int> > *v11; // ecx@1
      int *v12; // edi@3
      int *v13; // ecx@5
      int *v14; // esi@12
      int *v15; // eax@12
      std::vector<int,std::allocator<int> > *v17; // [sp-14h] [bp-3Ch]@1
      int v18; // [sp-10h] [bp-38h]@1
      int v19; // [sp-Ch] [bp-34h]@1
      int v20; // [sp-8h] [bp-30h]@1
      int v21; // [sp-4h] [bp-2Ch]@1
      std::vector<int,std::allocator<int> > foo; // [sp+0h] [bp-28h]@1
      int v23; // [sp+18h] [bp-10h]@15
      int v24; // [sp+1Ch] [bp-Ch]@1
      int (*v25)(); // [sp+20h] [bp-8h]@1
      int v26; // [sp+24h] [bp-4h]@1
    
      v26 = -1;
      v25 = _ehhandler__main;
      v24 = v6;
      v21 = v7;
      v20 = v8;
      v19 = v9;
      v18 = v10;
      v17 = (std::vector<int,std::allocator<int> > *)((unsigned int)&v18 ^ __security_cookie);
      std__vector_int_std__allocator_int____vector_int_std__allocator_int__(v11, (unsigned int)&foo);
      v4 = 0;
      v26 = 0;
      v3 = foo._Mylast;
      v5 = foo._Mylast;
      if ( foo._Myfirst > foo._Mylast )
      {
        __invalid_parameter_noinfo(v17, v18);
        v3 = foo._Mylast;
      }
      v12 = foo._Myfirst;
      if ( foo._Myfirst > v3 )
      {
        __invalid_parameter_noinfo(v17, v18);
        v3 = foo._Mylast;
      }
      v13 = v12;
      if ( v12 != v5 )
      {
        do
        {
          *v13 = 1337;
          ++v13;
        }
        while ( v13 != v5 );
        v3 = foo._Mylast;
      }
      while ( 1 )
      {
        if ( v4 >= (signed int)((char *)v3 - (char *)foo._Myfirst) >> 2 )
          __invalid_parameter_noinfo(v17, v18);
        v14 = &foo._Myfirst[v4];
        v15 = std__vector_int_std__allocator_int____at(v17, v4);
        _printf("operator[] : %d , at() : %d\n", *v14, *v15, v18);
        ++v4;
        if ( v4 >= 0xA )
          break;
        v3 = foo._Mylast;
      }
      if ( foo._Mylast )
        operator delete(foo._Mylast);
      foo._Mylast = 0;
      foo._Myend = 0;
      v23 = 0;
      operator delete(*(void **)&foo.baseclass_0.baseclass_0._Alaux.baseclass_0.dummy[0]);
      return 0;
    }
    

    bzw

    .text:00401060 ; int __cdecl main(int argc, const char **argv, const char **envp)
    .text:00401060 _main           proc near               ; CODE XREF: __tmainCRTStartup+10Ap
    .text:00401060
    .text:00401060 foo             = std::vector<int,std::allocator<int> > ptr -28h
    .text:00401060 var_10          = dword ptr -10h
    .text:00401060 var_C           = byte ptr -0Ch
    .text:00401060 var_8           = dword ptr -8
    .text:00401060 var_4           = dword ptr -4
    .text:00401060 argc            = dword ptr  8
    .text:00401060 argv            = dword ptr  0Ch
    .text:00401060 envp            = dword ptr  10h
    .text:00401060
    .text:00401060                 push    ebp
    .text:00401061                 mov     ebp, esp
    .text:00401063                 and     esp, 0FFFFFFF8h
    .text:00401066                 push    0FFFFFFFFh
    .text:00401068                 push    offset __ehhandler$_main
    .text:0040106D                 mov     eax, large fs:0
    .text:00401073                 push    eax
    .text:00401074                 sub     esp, 1Ch
    .text:00401077                 push    ebx
    .text:00401078                 push    ebp
    .text:00401079                 push    esi
    .text:0040107A                 push    edi
    .text:0040107B                 mov     eax, ___security_cookie
    .text:00401080                 xor     eax, esp
    .text:00401082                 push    eax             ; this
    .text:00401083                 lea     eax, [esp+3Ch+var_C]
    .text:00401087                 mov     large fs:0, eax
    .text:0040108D                 lea     eax, [esp+3Ch+foo]
    .text:00401091                 push    eax             ; _Count
    .text:00401092                 call    ??0?$vector@HV?$allocator@H@std@@@std@@QAE@I@Z ; std::vector<int,std::allocator<int>>::vector<int,std::allocator<int>>(uint)
    .text:00401097                 xor     ebx, ebx        ; _Pos
    .text:00401099                 mov     [esp+3Ch+var_4], ebx
    .text:0040109D                 mov     eax, [esp+3Ch+foo._Mylast]
    .text:004010A1                 mov     ebp, ds:__imp___invalid_parameter_noinfo
    .text:004010A7                 mov     esi, eax
    .text:004010A9                 cmp     [esp+3Ch+foo._Myfirst], eax
    .text:004010AD                 jbe     short loc_4010B5
    .text:004010AF                 call    ebp ; __imp___invalid_parameter_noinfo
    .text:004010B1                 mov     eax, [esp+3Ch+foo._Mylast]
    .text:004010B5
    .text:004010B5 loc_4010B5:                             ; CODE XREF: _main+4Dj
    .text:004010B5                 mov     edi, [esp+3Ch+foo._Myfirst]
    .text:004010B9                 cmp     edi, eax
    .text:004010BB                 jbe     short loc_4010C3
    .text:004010BD                 call    ebp ; __imp___invalid_parameter_noinfo
    .text:004010BF                 mov     eax, [esp+3Ch+foo._Mylast]
    .text:004010C3
    .text:004010C3 loc_4010C3:                             ; CODE XREF: _main+5Bj
    .text:004010C3                 mov     ecx, edi
    .text:004010C5                 cmp     edi, esi
    .text:004010C7                 jz      short loc_4010E1
    .text:004010C9                 lea     esp, [esp+0]
    .text:004010D0
    .text:004010D0 loc_4010D0:                             ; CODE XREF: _main+7Bj
    .text:004010D0                 mov     dword ptr [ecx], 539h
    .text:004010D6                 add     ecx, 4
    .text:004010D9                 cmp     ecx, esi
    .text:004010DB                 jnz     short loc_4010D0
    .text:004010DD                 mov     eax, [esp+3Ch+foo._Mylast]
    .text:004010E1
    .text:004010E1 loc_4010E1:                             ; CODE XREF: _main+67j
    .text:004010E1                 mov     edi, ds:__imp__printf
    .text:004010E7                 jmp     short loc_4010F4
    .text:004010E7 ; ---------------------------------------------------------------------------
    .text:004010E9                 align 10h
    .text:004010F0
    .text:004010F0 loc_4010F0:                             ; CODE XREF: _main+C5j
    .text:004010F0                 mov     eax, [esp+3Ch+foo._Mylast]
    .text:004010F4
    .text:004010F4 loc_4010F4:                             ; CODE XREF: _main+87j
    .text:004010F4                 sub     eax, [esp+3Ch+foo._Myfirst]
    .text:004010F8                 sar     eax, 2
    .text:004010FB                 cmp     ebx, eax
    .text:004010FD                 jb      short loc_401101
    .text:004010FF                 call    ebp ; __imp___invalid_parameter_noinfo
    .text:00401101
    .text:00401101 loc_401101:                             ; CODE XREF: _main+9Dj
    .text:00401101                 mov     ecx, [esp+3Ch+foo._Myfirst]
    .text:00401105                 lea     eax, [esp+3Ch+foo]
    .text:00401109                 lea     esi, [ecx+ebx*4]
    .text:0040110C                 call    ?at@?$vector@HV?$allocator@H@std@@@std@@QAEAAHI@Z ; std::vector<int,std::allocator<int>>::at(uint)
    .text:00401111                 mov     edx, [eax]
    .text:00401113                 mov     eax, [esi]
    .text:00401115                 push    edx
    .text:00401116                 push    eax
    .text:00401117                 push    offset Format   ; "operator[] : %d , at() : %d\n"
    .text:0040111C                 call    edi ; __imp__printf
    .text:0040111E                 inc     ebx
    .text:0040111F                 add     esp, 0Ch
    .text:00401122                 cmp     ebx, 0Ah
    .text:00401125                 jb      short loc_4010F0
    .text:00401127                 mov     eax, [esp+38h+foo._Mylast]
    .text:0040112B                 xor     esi, esi
    .text:0040112D                 cmp     eax, esi
    .text:0040112F                 jz      short loc_40113A
    .text:00401131                 push    eax             ; void *
    .text:00401132                 call    ??3@YAXPAX@Z_0  ; operator delete(void *)
    .text:00401137                 add     esp, 4
    .text:0040113A
    .text:0040113A loc_40113A:                             ; CODE XREF: _main+CFj
    .text:0040113A                 mov     ecx, dword ptr [esp+38h+foo.baseclass_0.baseclass_0._Alaux.baseclass_0.dummy]
    .text:0040113E                 push    ecx             ; void *
    .text:0040113F                 mov     [esp+3Ch+foo._Mylast], esi
    .text:00401143                 mov     [esp+3Ch+foo._Myend], esi
    .text:00401147                 mov     [esp+3Ch+var_10], esi
    .text:0040114B                 call    ??3@YAXPAX@Z_0  ; operator delete(void *)
    .text:00401150                 add     esp, 4
    .text:00401153                 xor     eax, eax
    .text:00401155                 mov     ecx, [esp+38h+var_8]
    .text:00401159                 mov     large fs:0, ecx
    .text:00401160                 pop     ecx
    .text:00401161                 pop     edi
    .text:00401162                 pop     esi
    .text:00401163                 pop     ebp
    .text:00401164                 pop     ebx
    .text:00401165                 mov     esp, ebp
    .text:00401167                 pop     ebp
    .text:00401168                 retn
    


  • @Icematix:
    Wie hast du den Pseudocode generieren lassen können?



  • drakon schrieb:

    @Icematix:
    Wie hast du den Pseudocode generieren lassen können?

    IDAPro 5.5 mit HexRays 1.1 (HexRays 1.2 ist die Bombe, erzeugt noch viel schöneren Pseudocode, absoluter Wahnsinn für Reverse Engineerer, hab ich leider noch nicht)

    Kostet dich aber ~1800€, wenn du nicht die Wege des Illegalen beschreiten möchtest 😉



  • Dachte ich doch, dass ich ein solches Feature in VS nicht übersehen könnte. 😉

    Danke für die Programme. Werde sie mir bei Gelegenheit mal anschauen.


Anmelden zum Antworten