Skip to content

Instantly share code, notes, and snippets.

@pavly-gerges
Last active December 1, 2024 09:03
Show Gist options
  • Save pavly-gerges/069e14c16ab4f1c5d643f11ebe18094d to your computer and use it in GitHub Desktop.
Save pavly-gerges/069e14c16ab4f1c5d643f11ebe18094d to your computer and use it in GitHub Desktop.
// The following code examines multiple routines of definining dynamic buffers in C.
// This file fires a runtime malloc() error due to a HEAP corruption error; because of buffer overflow.
// Two maneuvers are introduced to fix this
#include <stdio.h>
#include <stdlib.h>
int main() {
// buffers
const char *value1 = "Hi";
const char *value2 = "Hello\n Dynamic Buffers!";
// pointer to buffers
const char **inputs = malloc(sizeof(char *));
// automatic allocation of address buffer ???
// appends new addresses to the buffer automatically!
*inputs = value1;
*(inputs + 1) = value2;
*(inputs + 2) = value1;
*(inputs + 3) = value1;
*(inputs + 4) = value1;
// printf("%s\n", ((const char*) inputs[2]));
// printf("%s\n", ((const char*) inputs[2]));
free((void *) inputs);
return 0;
}
@pavly-gerges
Copy link
Author

pavly-gerges commented Nov 30, 2024

Caution

This solution introduces a memory access violation, and forceful write memory corruption, as debugged by Valgrind (see the invalid R/W on pre-allocated blocks!):

#include <stdio.h>
#include <stdlib.h>

int main() {
   
   // buffers
   const char *value1 = "Hi";
   const char *value2 = "Hello\n Dynamic Buffers!";
   
   // pointer to buffers
   const char **inputs = malloc(sizeof(char *));
   
   // automatic allocation of address buffer ???
   // appends new addresses to the buffer automatically!
   *inputs = value1;
   // allocate the buffers as needed 

   *(inputs + 1) = malloc(sizeof(char *));
   *(inputs + 1) = value1;
   *(inputs + 2) = malloc(sizeof(char *));
   *(inputs + 2) = value2;
   *(inputs + 3) = malloc(sizeof(char *));
   *(inputs + 3) = value1;
   *(inputs + 4) = malloc(sizeof(char *));
   *(inputs + 4) = value2;

   printf("%s\n", ((const char*) inputs[2]));
   printf("%s\n", ((const char*) inputs[3]));
   
   free((void *) inputs);


   return 0;
}

Valgrind memory debug:

pavl-x86-machine@pavl-g:../TestValgrindMemoryAccessVio$ valgrind ./a.out --leak-check=full
==14220== Memcheck, a memory error detector
==14220== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==14220== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==14220== Command: ./a.out --leak-check=full
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x1091D7: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a048 is 0 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x1091E6: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a048 is 0 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x1091FB: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a050 is 8 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x10920A: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a050 is 8 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x10921F: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a058 is 16 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x10922E: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a058 is 16 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x109243: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a060 is 16 bytes after a block of size 16 in arena "client"
==14220== 
==14220== Invalid write of size 8
==14220==    at 0x109252: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a060 is 16 bytes after a block of size 16 in arena "client"
==14220== 
==14220== Invalid read of size 8
==14220==    at 0x10925D: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a050 is 8 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
Hello
 Dynamic Buffers!
==14220== Invalid read of size 8
==14220==    at 0x109270: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220==  Address 0x4a8a058 is 16 bytes after a block of size 8 alloc'd
==14220==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==14220==    by 0x1091B5: main (in /media/pavl-x86-machine/pavl-g/Projects/TestValgrindMemoryAccessVio/a.out)
==14220== 
Hi
==14220== 
==14220== HEAP SUMMARY:
==14220==     in use at exit: 32 bytes in 4 blocks
==14220==   total heap usage: 6 allocs, 2 frees, 1,064 bytes allocated
==14220== 
==14220== LEAK SUMMARY:
==14220==    definitely lost: 32 bytes in 4 blocks
==14220==    indirectly lost: 0 bytes in 0 blocks
==14220==      possibly lost: 0 bytes in 0 blocks
==14220==    still reachable: 0 bytes in 0 blocks
==14220==         suppressed: 0 bytes in 0 blocks
==14220== Rerun with --leak-check=full to see details of leaked memory
==14220== 
==14220== For lists of detected and suppressed errors, rerun with: -s
==14220== ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 0 from 0)

@pavly-gerges
Copy link
Author

The following is a board summary to the 3 solutions presented here (incl. the defective solution that introduces memory access violations):

Memory-acces-vio

For more, follow the GNU Libc documentation for heap manipulating algorithms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment