The limits of "acceptable" code 
Author Message
 The limits of "acceptable" code

This is a little game you might use to test your knowledge of legal C
(or you might just skip the message :-)

Here is a program that Eric Bock (a friend of mine) and I cooked up.
It was an exercise in pushing the gcc compiler to its limits regarding
unspecified and undefined behavior.  The goal was to get the compiler
to generate as many warnings as possible in the least number of
characters, while still compiling the code into a program that prints
"Hello, world!" and does nothing else.

So, a small challenge -- how many errors can you find without
attempting a compile?  (I would be interested if any other compiler
besides gcc for Linux can deal with this.  I suspect not.)

#include "string.h"
#define h*p=printf("Hello??/, world!\n%.%r\010\010%\0%s",'
')+printf("")
const static char k$=500;
strcpy(char a){const auto char a=&a;return "s";}
long long*main(unsigned char a,char *b,const k){
  char h;
  if(p=&k)return;
  k,p;
a:k--?:1&&p==&p||k?k=p:&k;
  *main(&p,k++,a&1|p==a);
  if(printf("k: %*d",k));{}

Quote:
};/*/*/

#line 0
#ifdef 0
#endif    

With some compression (#define q char, and removing some verbosity),
this gets down to 150 characters and compiles under gcc with 62
warnings (-W -Wall -ansi -pedantic).  Perhaps this shows that gcc is
far too lenient in what it allows :-)

-Chris
--
http://www.*-*-*.com/ ~kern/index.html



Fri, 14 Mar 2003 08:52:35 GMT  
 The limits of "acceptable" code

Quote:

> This is a little game you might use to test your knowledge of legal C
> (or you might just skip the message :-)

> Here is a program that Eric Bock (a friend of mine) and I cooked up.
> It was an exercise in pushing the gcc compiler to its limits regarding
> unspecified and undefined behavior.  The goal was to get the compiler
> to generate as many warnings as possible in the least number of
> characters, while still compiling the code into a program that prints
> "Hello, world!" and does nothing else.

> So, a small challenge -- how many errors can you find without
> attempting a compile?

One's enough, surely? Your claim is that the program prints "Hello
world". Therefore, if I can prove that it either (a) doesn't or (b)
needn't, I've won and you've lost. ;-)

Quote:
> (I would be interested if any other compiler
> besides gcc for Linux can deal with this.  I suspect not.)

> #include "string.h"

Hmm. The official prejudice in comp.lang.c is for <string.h>

Quote:
> #define h*p=printf("Hello??/, world!\n%.%r\010\010%\0%s",'

What are you actually defining here? Which bit is the name and which bit
the value?

Quote:
> ')+printf("")

Syntax error.

Quote:
> const static char k$=500;

$ isn't a member of the source character set on all platforms. I'm
reasonably sure this requires a diagnostic.

Quote:
> strcpy(char a){const auto char a=&a;return "s";}

You've just invaded ISO namespace and interpositioned strcpy(), both of
which invoke undefined behaviour, I think.

Also, s is not an int, and a (the inner one) is not a pointer.

Quote:
> long long*main(unsigned char a,char *b,const k){

Don't start on main. Please, main has suffered enough abuse, wouldn't
you agree? Suffice to say that the above line causes behaviour. Which
kind of behaviour seems to depend on which way you squint at the
Standard and how much you've had to drink.

Quote:
>   char h;
>   if(p=&k)return;
>   k,p;
> a:k--?:1&&p==&p||k?k=p:&k;
>   *main(&p,k++,a&1|p==a);
>   if(printf("k: %*d",k));{}

Use of a variadic function without a prototype in scope invokes
undefined behaviour.

Quote:
> };/*/*/
> #line 0
> #ifdef 0
> #endif

> With some compression (#define q char, and removing some verbosity),
> this gets down to 150 characters and compiles under gcc with 62
> warnings (-W -Wall -ansi -pedantic).  Perhaps this shows that gcc is
> far too lenient in what it allows :-)

Not at all. As long as it correctly translates correct code, and
generates a diagnostic if the program contains a syntax error or
constraint violation, it's allowed to do whatever it likes with the
above junk.

Sorry. I meant, creative and highly polished and carefully-thought-out
junk.

Actually, no, that's wrong. I was right the first time.

--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
65 K&R Answers: http://users.powernet.co.uk/eton/kandr2/index.html (32
to go)



Fri, 14 Mar 2003 14:18:33 GMT  
 The limits of "acceptable" code
On Mon, 25 Sep 2000 07:18:33 +0100, Richard Heathfield

Quote:

>> (I would be interested if any other compiler
>> besides gcc for Linux can deal with this.  I suspect not.)

>> #include "string.h"

>Hmm. The official prejudice in comp.lang.c is for <string.h>

I was hoping that would generate a warning, but it didn't.

Quote:
>> #define h*p=printf("Hello??/, world!\n%.%r\010\010%\0%s",'

>What are you actually defining here? Which bit is the name and which bit
>the value?

The construct is #defining "h" to the rest of that value.  The "h*p"
generates a warning about "missing whitespace in #define".

Quote:
>> ')+printf("")

>Syntax error.

Sorry, that line break isn't there in the actual code, it was put in
by the newsreader.

Quote:
>Sorry. I meant, creative and highly polished and carefully-thought-out
>junk.

>Actually, no, that's wrong. I was right the first time.

It really is junk :)

-Chris
--
http://www.math.grinnell.edu/~kern/index.html



Fri, 14 Mar 2003 03:00:00 GMT  
 The limits of "acceptable" code
Groovy hepcat Chris Kern was jivin' on Mon, 25 Sep 2000 00:52:35 GMT
in comp.lang.c.
The limits of "acceptable" code's a cool scene! Dig it!

Quote:
>This is a little game you might use to test your knowledge of legal C
>(or you might just skip the message :-)

>Here is a program that Eric Bock (a friend of mine) and I cooked up.
>It was an exercise in pushing the gcc compiler to its limits regarding
>unspecified and undefined behavior.  The goal was to get the compiler
>to generate as many warnings as possible in the least number of
>characters, while still compiling the code into a program that prints
>"Hello, world!" and does nothing else.

>So, a small challenge -- how many errors can you find without
>attempting a compile?  (I would be interested if any other compiler
>besides gcc for Linux can deal with this.  I suspect not.)

>#include "string.h"

  Standard header namess should be enclosed in angle brackets, not
inverted commas.

Quote:
>#define h*p=printf("Hello??/, world!\n%.%r\010\010%\0%s",' ')+printf("")

  Hm, interesting! Of course, the trigraph ??/ expands to a backslash,
which then escapes the comma, causing undefined behaviour.
  The %. and %r and %\ sequences also cause undefined behaviour, not
being valid printf() conversion specifiers. My compiler (and most
others) probably won't complain about this, though.
  The same goes for the character constant argument. There isn't a
conversion specifier for a char or int, but there is one for a string,
but no string passed in.
  The octal values are non-portable. They may mean something to some
particular system. They could be meaningless elsewhere, or simply mean
something else. Again, I don't see my compiler complaining. The
behaviour, however, is implementation defined, I believe.
  Adding the return values of printf() calls is legal. It is purely
coincidence that int is both the declared (if the function had been
declared beforehand - which it wan't, of course) and default return
type.
  And, of course, calling undeclared variadic functions causes
undefined behaviour.
  And one more thing. The output is not terminated with a newline. I
think this is another case of undefined behaviour.

Quote:
>const static char k$=500;

  Invalid declarator. The dollar sign cannot be used in an identifier,
and $= is not an operator in C.

Quote:
>strcpy(char a){const auto char a=&a;return "s";}

  Reserved identifier. If string.h is found, then this identifier has
already been declared anyhow. And if string.h could not be found (as a
result of enclosing it in quotes instead of angle brackets), then
compilation would have already stopped with an error.
  Assigning an address to a non-pointer.
  Returning a pointer as an int.

Quote:
>long long*main(unsigned char a,char *b,const k){

  Pointer to long long return type for main(). Uh oh! :)  long long
isn't even a (C90) standard type. Too many arguments for main(). And
that declarator for argument k isn't strictly kosher. I'm not sure
whether this is even valid, or whether it's something gcc accepts but
is an invalid declarator in standard C.

Quote:
>  char h;

  Using the macro h, you are initialising a pointer (p) with an int
(the return values of the two printf() calls added together).

Quote:
>  if(p=&k)return;

  I'm still not sure about k. I don't know whether it will be valid or
not. But, you are assigning its address to p. Now, if k is a valid
object, then its type is probably int. So you are assigning the
address of an int to a pointer to char.
  Most compilers will warn about an assignment in an if(...) statement
anyhow. But it's legal (if the types are compatible - which they're
not in this case).
  You have declared main to return pointer to long long. Yet here you
return nothing.

Quote:
>  k,p;

  Meaningless. Does nothing. Besides, if k is a valid object, then its
address won't be NULL, so all this code below the if(...) statement
cannot be reached.

Quote:
>a:k--?:1&&p==&p||k?k=p:&k;

  Now, why do I feel a goto trying to rear its ugly head? Could it be
because of this label? It's legal, though.
  You don't know the initial value of k, so what good does it do to
decrement it?
  Expression omitted from ternary operation.
  p and &p have differing type.
  Assigning a pointer to char (p) to (probably) an int (k).
  Meaningless expression &k.

Quote:
>  *main(&p,k++,a&1|p==a);

  Dereferencing the return value of a function call, without doing
anithing with the value. Meaningless! However, it could also crash the
system or anithing if this code were ever to be executed, since the
pointer returned is random.
  &p is the wrong type for the first argument. k is the wrong type for
the second. And The comparison of p to a is probably invalid. They're
differing types.

Quote:
>  if(printf("k: %*d",k));{}

  Again, undefined behaviour. But since this code is not executed,
there's probably no problem. Too few arguments. Calling printf() in an
if(...) statement is legal, however.

Quote:
>};/*/*/
>#line 0
>#ifdef 0
>#endif

  These do nothing.

Quote:
>With some compression (#define q char, and removing some verbosity),
>this gets down to 150 characters and compiles under gcc with 62
>warnings (-W -Wall -ansi -pedantic).  Perhaps this shows that gcc is
>far too lenient in what it allows :-)

  Now, let's see how Watcom 10.6 reacts to this.

testing.c(3): Error! E1009: Expecting ';' but found '$'
testing.c(3): Error! E1061: Expecting data or function declaration,
but found '='
testing.c(3): Error! E1026: Invalid declarator
testing.c(3): Error! E1009: Expecting ';' but found '500'
testing.c(4): Error! E1062: Inconsistent return type for function
'strcpy'
testing.c(4): Error! E1071: Type of parameter 1 does not agree with
previous definition
testing.c(4): Error! E1151: Parameter count does not agree with
previous definition
testing.c(4): Error! E1057: Modifiers disagree with previous
definition of 'a'
testing.c(4): Error! E1034: Symbol 'a' already defined

  Damn! I missed that one. :)

testing.c(4): Error! E1010: Type mismatch
testing.c(4): Error! E1010: Type mismatch
testing.c(4): Warning! W202: Symbol 'a' has been defined, but not
referenced
testing.c(5): Error! E1060: Invalid type
testing.c(6): Error! E1010: Type mismatch
testing.c(7): Warning! W113: Pointer type mismatch
testing.c(9): Error! E1013: Constant variable cannot be modified

  Missed that one too.

testing.c(9): Error! E1063: Missing operand
testing.c(9): Warning! W113: Pointer type mismatch
testing.c(9): Error! E1013: Constant variable cannot be modified

  Again.

testing.c(9): Error! E1010: Type mismatch
testing.c(9): Error! E1010: Type mismatch

  I think I missed one of those. In fact, I still can't see it.

testing.c(10): Error! E1013: Constant variable cannot be modified

  Missed again.

testing.c(10): Error! E1010: Type mismatch
testing.c(10): Warning! W302: Expression is only useful for its side
effects
testing.c(11): Warning! W302: Expression is only useful for its side
effects
testing.c(12): Warning! W107: Missing return value for function 'main'

  The compiler apparently didn't notice that the statement
if(p=&k)return; returns every time.

testing.c(12): Warning! W118: Label 'a' has been defined but not
referenced
Error! E1147: Too many errors: compilation aborted
Error: Compiler returned a bad status compiling 'testing.c'
--

----- Dig the EVEN NEWER, MORE IMPROVED news sig!! -----

-------------- Shaggy was here! ---------------
    http://aardvark.apana.org.au/~phaywood/
============= Ain't I'm a dawg!! ==============



Mon, 17 Mar 2003 08:55:12 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Limiting stdin input to "n" chars

2. Limited debugging after "Attach to Process"

3. How to increase the limit "FOPEN_MAX"

4. remove() vrs fopen("""w")

5. Displaying binary data as ascii "1"'s and "0"'s

6. Looking for "Shroud"/"Obfus"

7. ""help with TSR""

8. Parse trees and "("")"

9. Error "free"-ing "malloc"-ed memory

10. Displaying binary data as ascii "1"'s and "0"'s

11. Hate new "tabbed" code document view

12. Help with slow "Generating Code..."

 

 
Powered by phpBB® Forum Software