[Cryptography] Ada vs Rust vs safer C

Ron Garret ron at flownet.com
Sat Sep 17 19:47:30 EDT 2016


On Sep 17, 2016, at 10:11 AM, Florian Weimer <fw at deneb.enyo.de> wrote:

> * Ron Garret:
> 
>> On Sep 17, 2016, at 8:55 AM, Florian Weimer <fw at deneb.enyo.de> wrote:
>> 
>>>> 4.  If you really REALLY want to win big, define a new language that
>>>> is just like C but where v[offset] and *(v+offset) are NOT equivalent
>>>> operations, and deprecate the latter.
>>> 
>>> Existing compilers already track pointer provenance information, the
>>> syntactic separation isn't really required.
>> 
>> Yes, it is.  There is a significant difference between x[y] and *(x+y)
>> despite the fact that the C standard specifies that these are
>> equivalent constructs: in *(x+y) the offset calculation and
>> dereference operation are *syntactically separable*, whereas in x[y]
>> they are not.  So in the case of x[y] the compiler can know that this
>> is an offset+dereference operation without having to do any analysis.
>> *(x+y) is just a special case of *(f(x,y)), and figuring out whether
>> or not that is equivalent to x[y] is uncomputable in general (it’s
>> equivalent to the halting problem).
>> 
>> This fact is reflected in real systems.  The following code:
>> 
>> int main(int argc, char* argv[]) {
>>  int x[100];
>>  int y = x[101];
>>  int z = *(x+101);
>>  return y+z;
>> }
>> 
>> generates one warning under clang, not two (and zero under gcc even with -Wall).
> 
> Recent GCC generates:
> 
> t.c: In function ‘main’:
> t.c:3:7: warning: ‘x[101]’ is used uninitialized in this function [-Wuninitialized]
>   int y = x[101];
>       ^
> t.c:4:7: warning: ‘*((void *)&x+404)’ is used uninitialized in this function [-Wuninitialized]
>   int z = *(x+101);
>       ^
> t.c:5:11: warning: ‘x[101]’ is used uninitialized in this function [-Wuninitialized]
>   return y+z;
>          ~^~
> 
> Not really pretty, I admit.
> 
> But if I change your example to:
> 
> int main(int argc, char* argv[]) {
>  int x[100] = {0};
>  int y = x[101];
>  int z = *(x+102);
>  return y+z;
> }
> 
> GCC still warns:
> 
> t.c: In function ‘main’:
> t.c:3:12: warning: array subscript is above array bounds [-Warray-bounds]
>   int y = x[101];
>           ~^~~~~
> t.c:4:7: warning: ‘*((void *)&x+408)’ is used uninitialized in this function [-Wuninitialized]
>   int z = *(x+102);
>       ^
> 
> So GCC tracks both expressions and knows that they are problematic
> because the subscript is out of bounds (although the GIMPLE
> representation is different).  I'm not sure if the warnings are issued
> from the same pass yet.

What matters here is that you get an array bounds warning for x[101] but NOT for *(x+102)

The use-of-uninitialized-data warnings are a red herring.  They have nothing to do with the point I was trying to make about the effective difference between x[y] and *(x+y).

rg



More information about the cryptography mailing list