<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
  <META NAME="GENERATOR" CONTENT="GtkHTML/3.12.3">
</HEAD>
<BODY>
On Fri, 2007-06-01 at 07:36 -0400, Matthew Saltzman wrote:
<BLOCKQUOTE TYPE=CITE>
<PRE>
<FONT COLOR="#000000">On Thu, 31 May 2007, Les wrote:</FONT>

<FONT COLOR="#000000">> On Thu, 2007-05-31 at 18:44 -0500, Mike McCarty wrote:</FONT>
<FONT COLOR="#000000">>> Les Mikesell wrote:</FONT>
<FONT COLOR="#000000">>>> Mike McCarty wrote:</FONT>
<FONT COLOR="#000000">>>></FONT>
<FONT COLOR="#000000">>></FONT>
<FONT COLOR="#000000">>> [Les wrote about "older" compilers]</FONT>
<FONT COLOR="#000000">>></FONT>
<FONT COLOR="#000000">>>>> Older? ANSI C is since 1989. I guess one could characterize 19 years</FONT>
<FONT COLOR="#000000">>>>> as "older". :-)</FONT>
<FONT COLOR="#000000">>>></FONT>
<FONT COLOR="#000000">>>></FONT>
<FONT COLOR="#000000">>>> C was old before ANSI came along.  Maybe we could revive the discussion</FONT>
<FONT COLOR="#000000">>>> of why "abcd"[2] must evaluate to 'c'.</FONT>
<FONT COLOR="#000000">>></FONT>
<FONT COLOR="#000000">>> I wasn't explicit enough, I guess. I wouldn't characterize</FONT>
<FONT COLOR="#000000">>> 19 years as "older", but rather as "antique" or "ancient"</FONT>
<FONT COLOR="#000000">>> in this context. I was objecting to using too weak a word,</FONT>
<FONT COLOR="#000000">>> not too strong a word :-)</FONT>
<FONT COLOR="#000000">>></FONT>
<FONT COLOR="#000000">> I'm sorry, I don't think of myself as antique or ancient.  You assume</FONT>
<FONT COLOR="#000000">> that all C compilers are ANSI compliant.  They are not.  K&R was around</FONT>
<FONT COLOR="#000000">> a long time before the standards committee got involved.  And although</FONT>
<FONT COLOR="#000000">> the standard may have been generated in 1989, Microsoft didn't implement</FONT>
<FONT COLOR="#000000">> the ANSI standard for several years after that, and then failed some of</FONT>
<FONT COLOR="#000000">> the standard tests.  SUN's compiler was not ANSII compliant until about</FONT>
<FONT COLOR="#000000">> 1994 or so.  There are many compilers out there, and most are probably</FONT>
<FONT COLOR="#000000">> not fully compliant either.  AND I do know that the variables are not</FONT>
<FONT COLOR="#000000">> initialized in many compilers.  I have fixed code for many, many people.</FONT>

<FONT COLOR="#000000">If static variables are not initialized, those compilers are broken.  K&R </FONT>
<FONT COLOR="#000000">woud tell you so even for pre-ANSI/ISO compilers.</FONT>

<FONT COLOR="#000000">> I know why their programs failed.  I also know that C uses a pushdown</FONT>
<FONT COLOR="#000000">                                                      ^some particular</FONT>
<FONT COLOR="#000000">                                                       implementations of</FONT>
<FONT COLOR="#000000">> stack for variables in subroutines.  You can check it out with a very</FONT>
<FONT COLOR="#000000">> simple program using pointers:</FONT>
<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">>    #include <sttlib.h></FONT>
<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">>    int i,j,k;</FONT>
<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">>    main()</FONT>
<FONT COLOR="#000000">>    {</FONT>
<FONT COLOR="#000000">>        int mi,mj,mk;</FONT>
<FONT COLOR="#000000">>        int *x;</FONT>
<FONT COLOR="#000000">>        mi=4;mj=5;mk=6;</FONT>
<FONT COLOR="#000000">>        x=&mk;</FONT>
<FONT COLOR="#000000">>        printf ("%d  %d  %d\n",*x++,*X++;*X++);</FONT>
<FONT COLOR="#000000">>        x=&i;</FONT>
<FONT COLOR="#000000">>        printf ("%d  %d  %d\n",*x++,*x++,*x++);</FONT>
<FONT COLOR="#000000">>        i-1;j=2;k=3;</FONT>
<FONT COLOR="#000000">>        printf ("%d  %d  %d\n",*x++,*x++,*x++);</FONT>
<FONT COLOR="#000000">>  )</FONT>
<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">> Just an exercise you understand.  compile and run this with several c</FONT>
<FONT COLOR="#000000">> packages, or if the package you choose supports it, have it compile K&R.</FONT>
<FONT COLOR="#000000">> and try it.</FONT>

<FONT COLOR="#000000">Of course, several constructs here are undefined, so there is no such </FONT>
<FONT COLOR="#000000">thing as "correct" or "incorrect" behavior.</FONT>

<FONT COLOR="#000000">After correcting obvious typos and adding #include <stdio.h> so it would </FONT>
<FONT COLOR="#000000">compile, I got (using gcc-4.1.1-51.fc6 with no options):</FONT>

<FONT COLOR="#000000">     $ ./a.out</FONT>
<FONT COLOR="#000000">     5  4  6</FONT>
<FONT COLOR="#000000">     0  0  0</FONT>
<FONT COLOR="#000000">     0 </FONT> 0  0
</PRE>
</BLOCKQUOTE>
OOPS, forgot to reset the X pointer between the last two print statements.  This bit of code is intended to show that globals are on a heap and locals are on a stack.
<BLOCKQUOTE TYPE=CITE>
<PRE>

<FONT COLOR="#000000">Was that what you were expecting?</FONT>


<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">> I cannot vouch for every compiler, only Microsoft, Sun, and Instant C</FONT>
<FONT COLOR="#000000">> off the top of my head.  I have used a few other packages as well.  But</FONT>
<FONT COLOR="#000000">> any really good programmer NEVER relies on system initialization.  It is</FONT>
<FONT COLOR="#000000">> destined to fail you at bad times.</FONT>

<FONT COLOR="#000000">How much effort are you willing to expend to defend against potentially </FONT>
<FONT COLOR="#000000">buggy compilers (as opposed to undefined or implementation-defined </FONT>
<FONT COLOR="#000000">behaviors)?  The Intel fdiv bug would seem to prove that you should NEVER </FONT>
<FONT COLOR="#000000">rely on arithmetic instructions to provide the correct answer.  There's an </FONT>
<FONT COLOR="#000000">economic tradeoff between protecting yourself from all conceivable errors </FONT>
<FONT COLOR="#000000">and actually getting work done.</FONT>

</PRE>
</BLOCKQUOTE>
There is a difference between implementation differences and hardware errors, which was the microsoft error.  They had <BR>
a bug in their silicon compiler that caused that IIRC.
<BLOCKQUOTE TYPE=CITE>
<PRE>
<FONT COLOR="#000000">>                                     One case is as has been pointed out</FONT>
<FONT COLOR="#000000">> here, that NULL is sometimes 0, sometimes 0x80000000, and sometimes</FONT>
<FONT COLOR="#000000">> 0xffffffff.  Even NULL as a char may be 0xFF 0xFF00 or 0x8000 depending</FONT>
<FONT COLOR="#000000">> on the implementation.  But strings always end in a character NULL or</FONT>
<FONT COLOR="#000000">> 0x00 for 8 bit ascii, if you use GNU, Microsoft, or Sun C compilers.</FONT>
<FONT COLOR="#000000">> They may do otherwise on some others.  It can byte (;-) you if you are</FONT>
<FONT COLOR="#000000">> not careful.</FONT>

<FONT COLOR="#000000">In your source code, NULL is *always* written 0 (or sometimes (void *) 0 </FONT>
<FONT COLOR="#000000">to indicate that it's intented to stand for a null pointer value, not a </FONT>
<FONT COLOR="#000000">NUL character value).  The string terminator character is *always* written </FONT>
<FONT COLOR="#000000">'\0'.  The machine's representation of that value is immaterial.  If you </FONT>
<FONT COLOR="#000000">type-pun to try to look at the actual machine's representation, your </FONT>
<FONT COLOR="#000000">program's behavior is undefined and you deserve what you get.  It's the </FONT>
<FONT COLOR="#000000">compiler's responsibility to ensure that things work as expected, no </FONT>
<FONT COLOR="#000000">matter what the machine's representation is.  (For example, '\0' == 0 must </FONT>
<FONT COLOR="#000000">return 1.)</FONT>

</PRE>
</BLOCKQUOTE>
'\0' is an escape forcing the 0, so of course this will be equal.
<BLOCKQUOTE TYPE=CITE>
<PRE>
<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">>    And since that is so, how are those variables initialized? and to</FONT>
<FONT COLOR="#000000">> what value?  What is a pointer set to when it is intialized.  Hint, on</FONT>
<FONT COLOR="#000000">> Cyber the supposed default for assigned pointers used to the the address</FONT>
<FONT COLOR="#000000">> of the pointer.  Again, system dependencies may get you.</FONT>

<FONT COLOR="#000000">Pre-ANSI/ISO compilers might have initialized static memory to </FONT>
<FONT COLOR="#000000">all-bits-zero even when that was not the correct representation of the </FONT>
<FONT COLOR="#000000">default for the type being initialized.  ANSI/ISO compilers are not </FONT>
<FONT COLOR="#000000">allowed to do that.  The required default initializations are well </FONT>
<FONT COLOR="#000000">defined.  (This is the sort of thing that motivates the creation of </FONT>
<FONT COLOR="#000000">standards in the first place.)</FONT>

<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">>    And those systems that used the first location to store the return</FONT>
<FONT COLOR="#000000">> address are not re-entrant, without other supporting code in the</FONT>
<FONT COLOR="#000000">> background.  I think I used one of those once as well.</FONT>

<FONT COLOR="#000000">There's no requirement for re-entrancy in K&R or ANSI/ISO.  In fact </FONT>
<FONT COLOR="#000000">several standard library routines are known to not be re-entrant.</FONT>

</PRE>
</BLOCKQUOTE>
This is true, but knowing that the base code is not reentrant due to design constraints or due to hardware constraints makes the difference on modern multithreaded systems, where the same executable memory can be used for the program (if the hardware allows that).
<BLOCKQUOTE TYPE=CITE>
<PRE>
<FONT COLOR="#000000">></FONT>
<FONT COLOR="#000000">>    PS.  A stack doesn't necessarily mean a processor call and return</FONT>
<FONT COLOR="#000000">> stack.  It is any mechanism of memory address where the data is applied</FONT>
<FONT COLOR="#000000">> to the current location, then the pointer incremented (or decremented</FONT>
<FONT COLOR="#000000">> depending on the architecture).</FONT>

<FONT COLOR="#000000">But usually in the context of discussions about compiler architectures, </FONT>
<FONT COLOR="#000000">call stacks are exactly what is meant.</FONT>

</PRE>
</BLOCKQUOTE>
I am not sure that is true, because in some implementations, the data heap and stack are in the same segment of memory, while the runtime stack for the processor is somewhere else.  For high security systems running  this should be a requirement.  It prevents obvious means of inserting malicious code through variable initialization, and then stack manipulation.  I say should be, because it has been tossed around from time to time, but I am unsure if it has ever been formalized.<BR>
<BR>
One system I worked on looked like this:<BR>
    init jump<BR>
    heap<BR>
    variable stack (push down)<BR>
    program entrance<BR>
    program<BR>
    local libraries<BR>
    relocation table<BR>
    symbol table (if not removed)<BR>
    machine stack<BR>
<BR>
    Unfortunately I no longer remember which system that was.  Just the fact that some standard libraries at that time would not run on it because they did manipulate the stack.<BR>
<BR>
Regards,<BR>
Les H
</BODY>
</HTML>