Hacking dynamic C ++ array

Purely curiosity, not to be used in production, because, obviously, this can cause serious problems.

With C ++, when assigning new memory ( var *ch = new char[x]), the size is stored essentially ch[-1]in accordance with the C ++ specifications.

The question is, is there a way to get this value? I tried:

char* ptr = ch;
--ptr
cout << *ptr;

// AND

cout << ch[-sizeof(char)];

So is there a way to hack this? Again, pure curiosity.

0
source share
3 answers

Disclaimer: never, never count on this job. Consider this β€œtoy code” only and never use it in β€œreal” software!

new malloc(), , , libc.

, char*, , , , size_t (4 32- ).

, :

#include <stddef.h>        // for size_t
#include <stdio.h>

void test(size_t size) {
    size_t result;
    char* p = new char[size];

    result = *((size_t*)p - 1);
    printf("Allocated:  %d (0x%X)  Preceding value: %d (0x%X)\n",
        size, size, result, result);

    delete p;
}

int main() {
    test(1);
    test(40);
    test(100);
    test(0x100);
    test(6666);
    test(0xDEAD);
    return 0;
}

, p size_t*, 1 ( sizeof(size_t) ).

:

$ ./a.exe
Allocated:  1 (0x1)  Preceding value: 19 (0x13)
Allocated:  40 (0x28)  Preceding value: 51 (0x33)
Allocated:  100 (0x64)  Preceding value: 107 (0x6B)
Allocated:  256 (0x100)  Preceding value: 267 (0x10B)
Allocated:  6666 (0x1A0A)  Preceding value: 6675 (0x1A13)
Allocated:  57005 (0xDEAD)  Preceding value: 57019 (0xDEBB)

, .


malloc/malloc.c glibc, :

  Alignment:                              2 * sizeof(size_t) (default)
       (i.e., 8 byte alignment with 4byte size_t). This suffices for
       nearly all current machines and C compilers. However, you can
       define MALLOC_ALIGNMENT to be wider than this if necessary.

  Minimum overhead per allocated chunk:   4 or 8 bytes
       Each malloced chunk has a hidden word of overhead holding size
       and status information

  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
              8-byte ptrs:  24/32 bytes (including, 4/8 overhead)

. , , , :

  • .
  • ( - ) " ".

, , " " :

#define SIZE        sizeof(size_t)
#define MAX(x,y)    ((x)>(y) ? (x) : (y))
#define align(x)    (((x)+2*SIZE-1) & ~(2*SIZE-1))
#define mask(x)     ((x) & ~0x3)

printf("align(size): 0x%X   mask(result): 0x%X\n\n",
    align(MAX(size+SIZE, 16)), mask(result));

SIZE 16. 2 * SIZE. , , 2 ANDed off. . :

$ ./a.exe
sizeof(size_t) = 4

size:  1 (0x1)  result: 19 (0x13)
align(size): 0x10   mask(result): 0x10

size:  40 (0x28)  result: 51 (0x33)
align(size): 0x30   mask(result): 0x30

size:  100 (0x64)  result: 107 (0x6B)
align(size): 0x68   mask(result): 0x68

size:  256 (0x100)  result: 267 (0x10B)
align(size): 0x108   mask(result): 0x108

size:  6666 (0x1A0A)  result: 6675 (0x1A13)
align(size): 0x1A10   mask(result): 0x1A10

size:  57005 (0xDEAD)  result: 57019 (0xDEBB)
align(size): 0xDEB8   mask(result): 0xDEB8

!


, :

$ uname
CYGWIN_NT-6.1-WOW64

$ g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

, . , .


. :

+4

. ++ , , . , - , delete [] pblah , ++ , . , , , , , , .

+2

, . MS VS2012 16- 16 , , sizeof(size_t) .

#include <iostream>

void test(size_t const size) 
{
  char * mem = new char[size];
  std::cout << "Number of allocated bytes at " << (size_t)mem;
  std::cout << " is: " << *(size_t*)(mem-16) << std::endl;
  delete [] mem;
}

void main()
{
  test(1U);
  test(40U);
  test(256);
  test(6666);
  test(57005);
  system("pause");
}

Number of allocated bytes at 101044204016 is: 1
Number of allocated bytes at 101044242832 is: 40
Number of allocated bytes at 101044242832 is: 256
Number of allocated bytes at 101044244064 is: 6666
Number of allocated bytes at 101044244064 is: 57005
DrΓΌcken Sie eine beliebige Taste . . .

  • 101044204016 / 16 = 6315262751
  • 101044242832 / 16 = 6315265177
  • 101044244064 / 16 = 6315265254

Als see ++

0

All Articles