3

I think reading memory should not cause any issue eg

char *d="";
char *d2="test";
memcmp(d,d2,10);

Can memcmp() ever fail ?

alk
  • 69,737
  • 10
  • 105
  • 255
Zxcv Mnb
  • 733
  • 8
  • 19
  • memcmp(0,0,10) will segfault... it assumes pointer parameters point to valid memory in your program. – amdn Mar 05 '14 at 19:41
  • 1
    @amdn, I am not sure about "will", since behavior is somewhat undefined. – s.bandara Mar 05 '14 at 19:42
  • @s.bandara you are right, it is undefined behavior, but it faults on every system I know of. – amdn Mar 05 '14 at 19:48
  • Part of the confusion may be that `memcmp` differs from `strcmp`... unlike `strcmp`, `memcmp` does not stop comparing after finding a null character, it continues for the number of bytes you specify or until it faults. – amdn Mar 05 '14 at 19:55
  • 1
    @amdn: "but it faults on every system I know of" - I highly doubt it... as long as it can read the next 5 bytes after `d2` it complete the comparison, so if the memory protection is arranged on a page size basis with pages large enough to hold both string literals it wouldn't fault, nor would it fault if further legitimately readable data elsewhere in the program happened to get packed in the 5 bytes after `d2`. – Tony Delroy Mar 05 '14 at 20:01
  • @TonyD I meant that dereferencing a null pointer, as in the example I gave of `memcmp(0,0,10)` will fault on every system I know of. – amdn Mar 05 '14 at 20:02
  • int main(int argc, char* argv[]) { return memcmp(argv[1],argv[2],1); } will segfault on every system I know of when invoked with less than two command line arguments (argc < 3). That's because argv[argc] is a null pointer. – amdn Mar 05 '14 at 20:29
  • 1
    @amdn: oh, fair enough then... :-). Would work on many systems 20 years ago, but no modern non-embedded systems I know of. – Tony Delroy Mar 05 '14 at 20:31

1 Answers1

5

Your assumption is incorrect, as reading memory at an address not mapped into the process's address space will cause a SEGV. Particularly reading address 0 (on almost all architectures), and reading kernel memory space (if it's even mapped in), but in general reading logical memory to which no physical memory is mapped as readable.

In your example you are running memcmp on bytes that are not allocated, which is undefined behaviour. It will probably read garbage from the stack or data segment, but you have no way of knowing that. For instance, d might be right at the top of the stack and you might thus run beyond the top of the stack into unmapped memory (the stack generally grows downwards).

abligh
  • 24,573
  • 4
  • 47
  • 84
  • "read garbage from the stack or data segment" / "`d` might be right at the top of the stack" - it doesn't matter where `d` itself is, as it's the reading `memcmp()` does from the address stored in `d` that's dangerous - we know that's been set to a string literal which will never be on the stack - traditionally it's in the data segment. – Tony Delroy Mar 05 '14 at 20:36
  • Won't memory for "d" be allocated in readonly section and not on function stack as Tony said ? – Zxcv Mnb Mar 06 '14 at 06:05
  • `d` is a pointer (`char *`) so `d` itself will not be read only. The data pointed to by `d` may be located in read only memory or may be in a writeable area; you have no guarantees as to where this is or as to its writeability, and there is nothing to prevent the compiler putting it (e.g.) at the top of the stack. The point is that the reading beyond it is undefined. – abligh Mar 06 '14 at 07:28