3

We know that strcat() recevies a poiner to a destination array as parameters and concatenate them with source string. The destination array should be large enough to store the concatenated result. Recently i found out that it is still possible for strcat() to execute as expected, for small programs, even when the destination array is not large enough to add second string. I start surfing stackoverflow and found out couple - answers for this question. I want to go more deeply,and understand what exactly happends in hardware layer when i run this code below ?

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>

using namespace std;

int main(){
    char p[6] = "Hello";
    cout << "Length of p before = " << strlen(p) << endl;
    cout << "Size of p before = " << sizeof(p) << endl;
    char as[8] = "_World!";
    cout << "Length of as before = " << strlen(as) << endl;
    cout << "Size of as before = " << sizeof(as) << endl;
    cout << strcat(p,as) << endl;
    cout << "After concatenation:" << endl;
    cout << "Length of p after = " << strlen(p) << endl;
    cout << "Size of p after = " << sizeof(p) << endl; 
    cout << "Length of as after = " << strlen(as) << endl;
    cout << "Size of as after = " << sizeof(as) << endl;

    return 0;
}

After running this code the length of array p[] is 12, and the size of p[] is 6. How can physically such length be stored on such array size ? I mean for this array the number of bytes are limited, so does it mean that strlen(p) function looks only for NULL terminator, and keeps counting untill it founds it and ignores the actual allocated size of that array. And sizeof() function doesn't really care if the last element in array, allocated purposely for null-character, is stores null-character or not.

casper
  • 259
  • 4
  • 18
  • Heap Overflow maybe? With a bit of time, when you start writing recursive functions, you may achieve Stack Overflow. – Stephen Quan Jun 30 '19 at 05:22
  • 2
    Possible duplicate of [An intended buffer overflow that does not always cause the program to crash](https://stackoverflow.com/questions/33013195/an-intended-buffer-overflow-that-does-not-always-cause-the-program-to-crash) – Alan Birtles Jun 30 '19 at 06:11

2 Answers2

6

The array p is allocated on the function stack frame, so strcat "overflows" the buffer p and continues wrting to some other area of the stack - typically it overrides other local parameters, function return address, etc (keep in mind that on x86 platform function stack usually grows "downwards", i.e. towards lesser addresses). This is well-known "buffer overflow" vulnerability.

strlen cannot know what is the actual size of your buffer, it just looks for 0-terminator. On the other hand, sizeof is a compile-time function that returns the array size in bytes.

Igor R.
  • 14,716
  • 2
  • 49
  • 83
1

You are writing outside the bounds of p and the behavior of your program is therefore undefined.

While the behavior is totally undefined, there are a couple of common behaviors that occur:

  1. You overwrite some unrelated data. This could be other local variables, the function return address, etc. It's impossible to guess exactly what will get overwritten without examining the assembly generated by the compiler for that specific program. This can result in a severe security vulnerability since it can allow an attacker to inject their own code into your program's memory space and let them overwrite a function's return address to cause the program to execute their injected code.

  2. The program crashes. This can happen if you write far enough past the end of the array to pass a memory page boundary. The program can try to write to a virtual memory address that the OS hasn't mapped to physical memory for your application. This results in the OS killing your application (with a SIGSEGV on Linux, for example). This will usually happen more often with dynamically allocated arrays than function-local arrays.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52