A safer interface for core.stdc

Johannes Pfau via Digitalmars-d digitalmars-d at puremagic.com
Sun Feb 8 02:54:58 PST 2015


Am Sat, 07 Feb 2015 15:50:53 -0800
schrieb Andrei Alexandrescu <SeeWebsiteForEmail at erdani.org>:

> I was looking into ways to make core.stdc safer. That should be 
> relatively easy to do by defining a few wrappers. For example:

This might be a good idea, but it might also be more difficult than you
think:

> 
> int  setvbuf(FILE* stream, char* buf, int mode, size_t size);
> 
> is unsafe because there's no relationship between buf and size. But
> this is fine:
> 
> @trusted int setvbuf(T)(FILE* stream, T[] buf, int mode)
> if (is(T == char) || is(T == byte) || is(T == ubyte))
> {
>      return setvbuf(stream, cast(char*) buf.ptr, mode, buf.length);
> }
> 

This can still cause memory corruption if `buf` is GC-allocated. You'd
have to pin the buffer which might not be easy in such a low-level
wrapper. OTOH in a higher level wrapper (std.stdio.File) you can simply
keep a reference to the buffer.

> Another example is:
> 
> int stat(in char*, stat_t*);
> 
> which may start reading through random memory if the string is not 
> zero-terminated. Again, the solution is here to ensure the string
> does have a terminating zero:
> 
> @trusted int stat(in char[] name, stat_t* p)
> {
>      if (isZeroTerminated(name)) return stat(name.ptr, p);

How would you implement `isZeroTerminated` in a memory safe way? We have
exactly the same problem in toStringz and nobody ever came up
with a really safe solution. The best you could do is using special
types for zero-terminated strings but that might be cumbersome to use.

>      auto t = cast(char*) malloc(name.length + 1);
>      scope(exit) free(t);
>      memcpy(t, name.ptr, name.length);
>      t[name.length] = 0;
>      return stat(t, p);
> }
> 
> Such wrappers would allow safe code to use more C stdlib primitives.
> The question is whether these wrappers are worth adding to
> core.stdc.stdio.
> 

That's the main question. There's only a limited amount of stdc
functions which can be wrapped in a safe way and std.stdio etc. are
already kind of a safe wrapper. And it's also important to get these
wrappers right and make sure they don't introduce memory safety bugs.



More information about the Digitalmars-d mailing list