[M3devel] unsafe functions that read/write raw memory, integer conversions, obligation of unsafe code?

Jay K jay.krell at cornell.edu
Sat Apr 24 23:20:49 CEST 2010


What is the obligation of stuff like:?


UNSAFE INTERFACE UnixIO;


PROCEDURE read(file:int; buffer: ADDRESS; length: INTEGER);
PROCEDURE write(file: int; ADDRESS; length: INTEGER);



The reason I ask is kind of tangential.

I'll explain it, but it again it doesn't necessarily matter:

In m3core/src/unix/Usocket.c we have, my doing:


/* assert that *plen fits in a 32 bit signed integer, no matter
if it is unsigned or signed, or 32 bits or 64 bits */

#define ASSERT_PLEN \
    assert((plen == NULL) || (((*plen)>= 0) && ((*plen) < (m3_socklen_t)(1UL << 30))));



Sometimes *plen is signed, sometimes unsigned.
I'm going to make it consistent from platform to platform.
I used to try to match the underlying platform and avoid copying.



The VMS C compiler is reasonably warning about *plen>= 0 always being true, given unsigned *plen.
So I'm wondering again what m3_socklen_t should be anyway.
There are at least four candidates:
   32bit signed int
   32bit unsigned int 
   pointer sized int (INTEGER)
   pointer sized unsigned integer (Word.T, which is INTEGER but with a different interpretation)


The numbers involves are always small and positive.
  It isn't a "buffer" size, but the size of a small struct.
Most 64bit C environments use a 32bit unsigned int. Though, again, we don't have to match them.
The comments I left say: Cygwin is 32bit int, HP-UX is size_t (32 or 64), the rest are unsigned int.
VMS is usually size_t, or int under old setting. An size_t is surprisingly always 32 bits.
But again the C settings aren't super relevant.


I'm thinking I should definitely make it unsigned.
That matches most platforms (which, again, doesn't matter), lets the assertion be cut in half, and thereby removing the warning.


But again, what is my "safety obligation"?
If some Modula-3 code passes in a "negative" number, am I doing a legitimate favor in failing an assertion?
Or they might just as well have passed in an incorrectly very large integer and overflowed their buffer just as well?
  Making negative numbers invalid seems useful at first glance, but then when you realize that pretty darn large numbers
   will still get through, it seems less useful.


Now, thinking about this more, it is not just about avoiding buffer overflow.
There is also the matter of truncating integers.
If some Modula-3 code passes me the value 4GB + 1 and I in turm truncate that to just 1, I have done something wrong.
Integer conversions have to be checked.
Therefore, for one thing, I think these wrappers do need to know with certainty what the underlying socken_t is.
  Even on platforms that don't declare it. :) Cygwin and VMS.


Asserting that they fit in a half range 32 bit integer is a way to avoid being completely precise.
It is acceptable here -- it not the size of a "buffer", but the size of a fairly small struct, a struct addr.


 - Jay

 		 	   		  


More information about the M3devel mailing list