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?

12
  • 4
    and are not " and '. What do you think is the result of b−a? Commented Jan 9, 2020 at 12:37
  • 7
    IIRC arithmetic between unrelated pointers (like a and b in your example) is undefined behavior. Commented Jan 9, 2020 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. Commented Jan 9, 2020 at 12:40
  • 2
    You do realise that malloc(x) can use more that x bytes - those extra bytes are for housekeeping. Commented Jan 9, 2020 at 12:42
  • 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. Commented Jan 9, 2020 at 12:55

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.