0

This code is writing an extra character at memset, but why?

int main(int argc, char ∗argv[]) {

    char ∗a, ∗b;
    a=(char ∗)malloc(12);
    b=(char ∗)malloc(12);

    if(!a || !b)
        err(2, "malloc error.\\n");

    bzero(a, 12); bzero(b, 12);
    printf("%x %x (%i)\n", a, b, b−a); // b−a is d.
    memset(a, (int)'a', 11);
    memset(b, (int)'b', 11);
    printf("a: %s\n", a);
    printf("b: %s\n", b);
    printf("−−−\n");
    memset(a, (int)'a', b−a); // Heap−Overflow? Is this happening here ?
    printf("a: %s\n", a);

    free(a);
    free(b);
    return 0;
}

vulnerability? In case this would be a password, there would be an extra character after every print?

dragosht
  • 3,237
  • 2
  • 23
  • 32
  • 4
    `”` and `’` are not `"` and `'`. What do you think is the result of `b−a`? – KamilCuk Jan 09 '20 at 12:37
  • 7
    IIRC arithmetic between unrelated pointers (like `a` and `b` in your example) is undefined behavior. – Some programmer dude Jan 09 '20 at 12:39
  • 2
    Also note that to print a (`void *`) pointer you should use the `%p` format specifier. And the result of pointer subtraction is (IIRC) a `size_t` which should be printed with `%zu`. Mismatching format specifiers and argument types leads to undefined behavior. – Some programmer dude Jan 09 '20 at 12:40
  • 1
    @KamilCuk gedit copied this wrong out , dunno why. I just edited the post. i am not sure about ur second answer – Tsolakidis Konstantinos Jan 09 '20 at 12:42
  • 2
    You do realise that `malloc(x)` can use more that `x` bytes - those extra bytes are for housekeeping. – Ed Heal Jan 09 '20 at 12:42
  • 1
    Lastly, in C you don't have to (and really shouldn't) [cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – Some programmer dude Jan 09 '20 at 12:44
  • 1
    You say `%i` to print `b-a` prints `d.` which makes no sense. Please clarify. – hyde Jan 09 '20 at 12:45
  • 1
    You don't need to cast `(int)'a'` either: `'a'` is already type `int`. – Weather Vane Jan 09 '20 at 12:51
  • 1
    There is no guarantee that `b` is greater than `a` or that they have any relation to each other at all, and as mentioned, it is *undefined behaviour* when you try to relate them. – Weather Vane Jan 09 '20 at 12:53
  • The main problem here is `b−a` which is undefined behaviour or at least `b-a` is a nonsensical value. Then using `memset(a, (int)'a', b−a);` results also inundefined behaviour. – Jabberwocky Jan 09 '20 at 12:54
  • 2
    @Someprogrammerdude, the result of a (well-defined) pointer subtraction is a `ptrdiff_t`, which is not necessarily the same type as `size_t`. The best way to print one is probably to first cast it to an integer type whose format specifier you know. – John Bollinger Jan 09 '20 at 12:55
  • Please don't write C code in MS Word or whatever you used for this. This code is full of non-standard symbols and won't compile. – Lundin Jan 09 '20 at 13:00

2 Answers2

6

You cannot use pointer arithmetic on pointers that point at separate arrays. a and b are two different arrays.

C17 6.5.6 emphasis mine:

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

Therefore b-a does not have a well-defined result. It could be anything. Therefore the memset(... , b-a); invokes undefined behavior and likely writes out of bounds of the array. Or the compiler could just replace b-a with zero.

In addition, there is by no means any guarantee that a and b are allocated adjacently in memory. The heap manager part of the dynamic allocation functions may add size bytes and padding bytes anywhere. The heap might be segmented and force the allocation to be done in wildly different places. Or b could be allocated at a lower address than a, since there is no requirement that heaps use up-counting allocation. (Most stacks use down-counting, as an example.)

So yes, this is very vulnerable because the whole program is full of bugs and may crash at any point. "Heap overflow", if such a term exists, would rather refer to all memory of the heap being used, and that's not what's happening here.

Lundin
  • 195,001
  • 40
  • 254
  • 396
4

b-a minimum positive value might be 8 bytes of header, 12 bytes of your data, rounded up to nearest multiple of 8, so 24. It might also be negative, there is no guarantee that b is at larger address than a. It could also be anything else or make your program do whatever, as pointer arithmetic between unrelated (not same array or allocated buffer) pointers is Undefined Behavior.

But let's assume it is valid value 24 (Undefined Behavior certainly allows it to be what you expect, because it allows anything). You memset 24 bytes into a buffer of size 12. This is buffer overflow.

hyde
  • 60,639
  • 21
  • 115
  • 176