Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c > #1635

Re: Second draft, "Safe arrays and pointers for C"

From John Nagle <nagle@animats.com>
Newsgroups comp.std.c
Subject Re: Second draft, "Safe arrays and pointers for C"
Date 2012-08-31 17:26 -0700
Organization A noiseless patient Spider
Message-ID <50415632.6060606@animats.com> (permalink)
References <503FC37F.8050701@animats.com> <k1rd60$f4s$1@speranza.aioe.org>

Show all headers | View raw


On 8/31/2012 3:17 PM, Alan Curry wrote:
>> Buffer overflows continue to plague C and C++ programs.
>                                                         ^
>                                                         |
> [citation needed]---------------------------------------/
> 
> Seriously, got any statistics to support this? What's the percentage of bugs
> (or percentage of security holes in particular) that are buffer overflows?

   CERT advisories for newly discovered buffer overflows in C programs
continue to come out. Analysis of the CERT database might be helpful here.

> With words like "plague" and no actual numbers, the whole basis for the
> proposal looks like a personal grudge.

   Yes.  I don't like programs crashing.

>> Features imported from C++11
>> o o o References auto decltype
> 
> I don't do C++. Is decltype just a respelling of typeof?

   Essentially, yes.  "decltype" is standard C++11. "typeof" is a
nonstandard GCC extension.

> I do know C++ reference syntax and it's stupid. 

   Sounds like a personal grudge.

>> Unions may not contain pointer or reference types, and all parts of a union
>> must have the same length.
> 
> So unions just became useless...

   Not really.  The main use case for unions is for data read
in from an external source, often a network.  Such data should
not contain pointers or references.

>> To be modified by pointer arithmetic, a pointer variable must be initialized
>> at declaration to an element of an array. Subscripting a pointer is allowed,
>> but the result is read-only ("const").
> 
> So after all this effort, unintended read accesses via buffer overflow are
> still allowed?

   Tightening down the screws further on that would alienate too many C
programmers.  Consider the common idiom

	const char* msg[] =
	{"First message", "second message", "third message", 0 }

Or even
	int main(int argc, const char* argv[]);

Most security attacks require write access.

It might be possible to tighten this down more by restricting such
unchecked access to type char (and wchar_t perhaps) only.  This
is a common idiom for strings, but not that common otherwise.

> 
>> Fixed-length arrays in C and C++
> [...]
>> This is valid C++ today. C++ already supports the concept of a reference to
>> an array. (Arrays of references are prohibited by the C++ standard, but
>> references to arrays are not.) Where the compiler knows the length of an
>> array, we can acces that informatio via sizeof. This is convenient, but only
> 
> Typos (acces, informatio)

   Will fix.

>> When a known-length array is defined or passed as a parameter, its length is
>> the value of the dimension expression evaluated at initialization time. This
>> follows the usage for C99 variable length array parameters. This feature
>> allows a function such as the following:
>> void copybyref(size_t n, int (&a)[n], const int (&b)[n]) {
>>  for (int i = 0; i < lengthof(a); i++) {
>>    a[i] = b[i];
>>  }
>> }
> 
> There is existing syntax (since C99) that I think you're overlooking for the
> prototype:
> 
> void copybyref(size_t n, int a[static n], const int b[static n])

   This was discussed at length back at
"Initial draft proposal: "Safe arrays and pointers for C"".
C99 VLA parameters are delivered to the called function as
a pointer, with the length of the first dimension lost.
Changing that might break some existing program.

    C99 VLA parameters seem to be on the way out, anyway.
In C11, they're an optional feature.  Microsoft refused
to implement them.  And they don't play well with C++
because they weren't designed with function overloading
in mind.

   There's some discussion in the current rev
of the paper on how to make C++ function overloading play
well with these reference parameters, but it's not fully
developed.  That's beyond the scope of this proposal,
but it should be possible to prevent unnecessary divergence
between C and C++.  (Quick note on name mangling: evaluate
all constants in array length expressions down to integers,
rename function params in some positional way like $1, $2,
etc. construct a string which represents the expression
for name matching purposes, and insert that into the
mangled name string at the appropriate point.)


> 
>> If the programmer calls "copybyref" as follows:
>> copybyref(lengthof b0, b0, a0);
>> The checks become
>> lengthof(b0) == lengthof(b0)
>> engthof(a0) == lengthof(b0)
> 
> Typo (engthof)

   Will fix.

>> For example, the classic UNIX read call would now be expressed as:
>> int read(size_t n; int fd, void_space(&buf)[n], size_t n);
>> (The type void_space is discussed below; it's simply a type with a size of
>> 1, usable for arrays, for which the bytes have no predetermined meaning.
>> Think of it as void* with length. The initial "size_t n;" is a forward
>> declaration, discussed below.)
> 
> void_space is like a hybrid between a void and a char... I think I'd call it
> "void char" (it fits in with "signed char" and "unsigned char" as another
> variant of the basic 1-byte type). And typedef it as vchar or voidc.

    That might be a good idea.  Would "void char" as a type break
anything?  Need advice from a syntax expert here.
> 
>> Worth noting is that the function declaration of read above is, in
>> non-strict mode, compatible with existing code which passes buf as a pointer
>> to a char.
> 
> What about existing code which passes a pointer to a struct, and n is the
> sizeof the struct (or maybe a multiple of the sizeof the struct)? Do all
> pointers convert to void_space &[] as easily as they convert to void *?

    If the size matches, yes.  That's the point of "void_space".  Type
matching works like "void", but size works like "char".

>> A struct with an array as the last component
>> An especially useful idiom is a structure with an array as the last
>> component. C supports this now, but the size of the array is always
>> undefined, expressed with [ ] . This proposal allows such arrays to be of
>> known size. The array, and the structure, then have a known size. and A
>> simple example is
>> typedef struct msgitem {
>>  const size_t len;
>>  char itemvalue[len];
>> };
>> struct msgitem firstmsg = { 100, 0 }; // empty msgitem, size 100
> 
> What's that typedef doing there?

    Will fix.

> This looks nice, but I had an idea for an explicit syntax marker to show that
> an earlier struct element is being referred to. The designated initializer
> syntax.
> 
> struct msgitem {
>   const size_t len;
>   char itemvalue[.len];
> };
> 
> I'm not sure this is better.

   The leading "." seems strange.  I'd just start the search for "len"
with the fields of the current struct, then any outer struct, then outer
scopes. Anything found in an outer scope has to be a compile-time
constant.

> 
> The const brings up an important point too. Obviously it's meant to prevent
> the len being changed after the struct is allocated. Would you disallow the
> declaration without the const?

   Yes. You can replace the entire struct by assignment, though.

>> Associating length with an array pointer in a structure
>> Alternatively, a user might want a structure which carries both the array
>> and its size. The pointer-based form is typedef str { size_t len, char*
>> data}; New reference form: typedef str { size_t len, char (&data)[len]); ...
>> str s1 = {n, MALLOC(char, n) }; // structure initialization The key point
>> here is that char (&data)[len] is a reference to a string of known length.
>> As in the previous example, len, is an element in the same structure, and
>> ties the length of the array to a value which can be found from the
>> structure. Multiple arrays may be present in the same structure. However,
>> all such arrays must be allocated during structure initialization, because a
>> reference cannot be null.
> 
> Here I think you're reaching too far. You can't just decree that a bunch of
> dynamic allocations succeed or fail as some kind of atomic group. You have to
> allow for cleanup after the first one succeeds and the second one fails. And
> the more you try to hide that cleanup, the less like C your language becomes.

    I'm merely suggesting that an allocation function be provided
that calls some global function on an out of memory condition. It's
still possible to do it the hard way, with recovery from each failed
allocation.  But a fail-on-allocate feature could be useful.  It's
not going to clean up without memory leaks, as can be done in C++.
I'm just suggesting that as a convenience feature.
> 
>>From Numerical Recipes in C, Gauss-Jordan elimination:
>> Original function declaration:
>> void gaussj(float **a, int n, float **b, int m);
>> New form:
>> void gaussj(int m; float (a&)[n][n], int n, float (&b)[n][m], int m);
> 
> Are those meant to be ABI-equivalent? I don't see how they can be. The first
> one implies that there is actually an array of pointers to float somewhere in
> memory, and that the full two-dimensional array of floats doesn't have to be
> contiguous.

   Good point.  Can't quite do that one compatibly.  Most arrays
passed that way are in fact contiguous, but they don't have to be.

				John Nagle


Back to comp.std.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Second draft, "Safe arrays and pointers for C" John Nagle <nagle@animats.com> - 2012-08-30 12:48 -0700
  Re: Second draft, "Safe arrays and pointers for C" pacman@kosh.dhis.org (Alan Curry) - 2012-08-31 22:17 +0000
    Re: Second draft, "Safe arrays and pointers for C" John Nagle <nagle@animats.com> - 2012-08-31 17:26 -0700
      Re: Second draft, "Safe arrays and pointers for C" Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2012-09-02 22:20 +0200
        Re: Second draft, "Safe arrays and pointers for C" BGB <cr88192@hotmail.com> - 2012-09-03 10:55 -0500
          Re: Second draft, "Safe arrays and pointers for C" Ike Naar <ike@iceland.freeshell.org> - 2012-09-03 16:39 +0000
            Re: Second draft, "Safe arrays and pointers for C" BGB <cr88192@hotmail.com> - 2012-09-03 13:18 -0500
  Re: Second draft, "Safe arrays and pointers for C" Jens Gustedt <jens.gustedt@loria.fr> - 2012-09-02 10:52 +0200
  Re: Second draft, "Safe arrays and pointers for C" Per <per.mathisen@gmail.com> - 2012-09-28 06:49 -0700
    Re: Second draft, "Safe arrays and pointers for C" John Nagle <nagle@animats.com> - 2012-09-28 11:36 -0700
      Re: Second draft, "Safe arrays and pointers for C" Per <per.mathisen@gmail.com> - 2012-10-01 09:38 -0700
        Re: Second draft, "Safe arrays and pointers for C" John Nagle <nagle@animats.com> - 2012-10-01 11:38 -0700
      Re: Second draft, "Safe arrays and pointers for C" Shao Miller <sha0.miller@gmail.com> - 2012-12-17 09:11 -0500
        Re: Second draft, "Safe arrays and pointers for C" Keith Thompson <kst-u@mib.org> - 2012-12-17 10:18 -0800
          Re: Second draft, "Safe arrays and pointers for C" Shao Miller <sha0.miller@gmail.com> - 2012-12-17 18:24 -0500
            Re: Second draft, "Safe arrays and pointers for C" Shao Miller <sha0.miller@gmail.com> - 2012-12-17 18:32 -0500
            Re: Second draft, "Safe arrays and pointers for C" Keith Thompson <kst-u@mib.org> - 2012-12-17 15:44 -0800

csiph-web