JG Posted:
A lot of C++ code allocates a buffer and initializes
start and end pointers as follows:
+-------------------------------+
+ +
+-------------------------------+
^ ^
| |
pStart pEnd
setting pEnd = pStart + bufLen
Indeed.
size_t const buf_size = 512;
char unsigned *const p = (char unsigned*)malloc(buf_size);
char unsigned const *const pover = p + buf_size;
But what if the buffer is allocated at the very end of memory
and just fits. Then pEnd == MEM_MAX + 1 == 0
That's a possible way of doing it, yes.
and so library users could tamper with code by creating a buffer of
suitable size. Can this happen in practice?
I don't understand what you're saying. . . how could they tamper with code?
Phlip:
The C++ Standard reputedly declares that pointing and indexing
one-off-the-end of an array is well-defined. (Copying out the value of
that bogus element is undefined, except if the element is a char, where
it's simply garbage.)
That's incorrect; the behaviour of the following is undefined:
int main()
{
char buf[12];
buf[12];
}
That means a C++ implementation may not, for example, place any array
right at the end of memory, such that its one-off-the-end location
occupies an overflowed pointer value, or a storage location protected by
hardware.
The C++ Standard imposes no such restriction.
The whole "pointer to one past last" concept has been discussed in depth
many times. Things to note are:
(1) The null pointer value need not be represented by all bits zero.
(2) Pointer arithmetic need not be calculated internally in the same
fashion that unsigned arithmetic is (i.e. wrap-around overflow).
(3) The "pointer to one past last" may compare equal to null.
This leaves the door wide open for implementors, just so long as the code
behaves as it should.
--
Frederick Gotham