jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) (09/15/90)
Well... if I do the following, lstat() doesn't work: struct stat *sbuf; lstat("/unix", sbuf); But this DOES: struct stat sbuf; lstat("/unix", &sbuf); It looks like in case #1, sbuf is pointing somewhere dangerous and when lstat is called, memory is destroyed... -- ======================================================================= #include <std/disclaimer.h> =:^) Jim Jagielski NASA/GSFC, Code 711.1 jim@jagmac2.gsfc.nasa.gov Greenbelt, MD 20771 "Kilimanjaro is a pretty tricky climb. Most of it's up, until you reach the very, very top, and then it tends to slope away rather sharply."
dyer@spdcc.COM (Steve Dyer) (09/15/90)
In article <3422@dftsrv.gsfc.nasa.gov> jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) writes:
]Well... if I do the following, lstat() doesn't work:
] struct stat *sbuf;
] lstat("/unix", sbuf);
]But this DOES:
] struct stat sbuf;
] lstat("/unix", &sbuf);
]
]It looks like in case #1, sbuf is pointing somewhere dangerous and when lstat
]is called, memory is destroyed...
OK, so where's the bug? You've not understood the C language.
Just where do you think sbuf is pointing to in the first example?
If you don't assign a value to a variable, how can you expect to
use its value as something meaningful?
--
Steve Dyer
dyer@ursa-major.spdcc.com aka {ima,harvard,rayssd,linus,m2c}!spdcc!dyer
dyer@arktouros.mit.edu, dyer@hstbme.mit.edu
liam@cs.qmw.ac.uk (William Roberts) (09/17/90)
In <4038@ursa-major.SPDCC.COM> dyer@spdcc.COM (Steve Dyer) writes: >In article <3422@dftsrv.gsfc.nasa.gov> jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) writes: >]Well... if I do the following, lstat() doesn't work: >] struct stat *sbuf; >] lstat("/unix", sbuf); >]But this DOES: >] struct stat sbuf; >] lstat("/unix", &sbuf); >] >]It looks like in case #1, sbuf is pointing somewhere dangerous and when lstat >]is called, memory is destroyed... >OK, so where's the bug? You've not understood the C language. >Just where do you think sbuf is pointing to in the first example? >If you don't assign a value to a variable, how can you expect to >use its value as something meaningful? Or, slightly less harshly, you have some further nuances to learn about how to read the UNIX section2 & 3 manual pages. In particular, when you see pointers being used you must ask yourself "Who is allocating the memory for this?" - in the case of pointers passed as arguments, the answers is ALWAYS that the caller allocates the memory since C uses call by value. When you see pointers to pointer as arguments, or pointers as return values then there is a possibility that the called routine will do the memory allocation (e.g. getpwuid). True system calls ALWAYS use pointers (because they are small and easy to pass into the kernel) and ALWAYS require the user process to provide the memory. -- William Roberts ARPA: liam@cs.qmw.ac.uk Queen Mary & Westfield College UUCP: liam@qmw-cs.UUCP Mile End Road AppleLink: UK0087 LONDON, E1 4NS, UK Tel: 071-975 5250 (Fax: 081-980 6533)
jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) (09/17/90)
In article <4038@ursa-major.SPDCC.COM> dyer@ursa-major.spdcc.COM (Steve Dyer) writes: >In article <3422@dftsrv.gsfc.nasa.gov> jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) writes: >]Well... if I do the following, lstat() doesn't work: >] struct stat *sbuf; >] lstat("/unix", sbuf); >]But this DOES: >] struct stat sbuf; >] lstat("/unix", &sbuf); >] >]It looks like in case #1, sbuf is pointing somewhere dangerous and when lstat >]is called, memory is destroyed... > >OK, so where's the bug? You've not understood the C language. >Just where do you think sbuf is pointing to in the first example? >If you don't assign a value to a variable, how can you expect to >use its value as something meaningful? > In the 1st case, before the call, sbuf is set to NULL, thus ensuring that it points to nothing, so my comment that it is pointing somewhere dangerous is wrong (this setting of sbuf IS done in my program but was NOT included in my posting... sorry). The following WILL work (although it may NOT be portable and is NOT mentioned in K&R): int *pint; pint = NULL; *pint = 10; Now some C compilers (such as GreenHills and Vax-C) will accept lstat("/unix", sbuf) and some won't. ALL will accept lstat("/unix",&sbuf) (assuming, of course, that sbuf is defined correctly, 'natch). As was mentioned in a mail message to me, some compilers may push a pointer to the struct in both cases, (although this does NOT adhere to the X3J11 standard, which says that when a structure is passed, the function gets an IMAGE of the structure). Therefore, in the compilers that DO accept this, the function is either getting a pointer or else the original structure. (observe that lstat expects a pointer to a struct) In any case, the second method (passing &sbuf) IS portable and is standard. This is NOT, however, picked up by lint... PS: This program was a port from VaxC, which ran it with no problem. It was and old piece of code which I did very quick-and-dry... PPS: I understand C quite well thank you... that is, when my brain isn't mush (which lately seems QUITE often :) -- ======================================================================= #include <std/disclaimer.h> =:^) Jim Jagielski NASA/GSFC, Code 711.1 jim@jagmac2.gsfc.nasa.gov Greenbelt, MD 20771 "Kilimanjaro is a pretty tricky climb. Most of it's up, until you reach the very, very top, and then it tends to slope away rather sharply."
dyer@spdcc.COM (Steve Dyer) (09/17/90)
In article <3430@dftsrv.gsfc.nasa.gov> jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) writes: >In the 1st case, before the call, sbuf is set to NULL, thus ensuring that it >points to nothing, so my comment that it is pointing somewhere dangerous is >wrong (this setting of sbuf IS done in my program but was NOT included in >my posting... sorry). Sigh. You were a Pascal programmer in a previous life, I'll bet. Um, it doens't point to nothing, it points to the memory location pointed to by NULL. This is usually location 0. >The following WILL work (although it may NOT be portable and is NOT mentioned >in K&R): > > int *pint; > pint = NULL; > *pint = 10; K&R or ANSI C don't prevent you from writing incorrect programs. Unless you have explicit control over the loading of your program (say, under an embedded system), and you KNOW that memory starting at location 0 (and going on for however long) is a valid destination, you simply can't say anything whatsoever about whether this code fragment works. You might as well be arguing that the following works: int *pint; pint = 476; *pint = 10; Now, some architectures have location 0 mapped into a user's process space as writable, and will gleefully allow you to overwrite whatever is there. On such architectures, location 0 frequently points to once-only startup code, so since you never re-execute the now corrupted machine code, you'll never notice the problem. More modern architectures make such code segments read-only and sharable to begin with, so such an attempt to overwrite the segment will fail. Even in architectures where location 0 points to the user's data space, such an assignment (or the call to stat/lstat) holds the possibility of corrupting whatever the loader decided to place there. Such architectures (like the PDP-11 I&D machines) always reserve the first word of the data segment which starts at 0 so that no variable address would have the value 0 (that is, to insure that &var will never equal NULL). On such architectures, your example above would "succeed", but the call to stat/lstat would still corrupt additional memory because the system call would attempt to overwrite sizeof(struct stat) bytes and not the sizeof(int) bytes in your example above. It might not cause an exception, but that doesn't mean that it's correct in any sense of the word. Presumably you had some data stored in those subsequent memory locations which is now trash. >Now some C compilers (such as GreenHills and Vax-C) will accept lstat("/unix", >sbuf) and some won't. ALL will accept lstat("/unix",&sbuf) (assuming, of >course, that sbuf is defined correctly, 'natch). As was mentioned in a mail >message to me, some compilers may push a pointer to the struct in both cases, >(although this does NOT adhere to the X3J11 standard, which says that when >a structure is passed, the function gets an IMAGE of the structure). Therefore, >in the compilers that DO accept this, the function is either getting a pointer >or else the original structure. (observe that lstat expects a pointer to >a struct) This is not a standards issue. I don't see anywhere in your examples: struct stat *sbuf; lstat("/unix", sbuf); versus struct stat sbuf; lstat("/unix", &sbuf); where the issue of compilers enters in. ANY compiler should accept either of these, and in both examples, there is no confusion about what it should do. Issues of structure passing and how it's implemented are not relevant here because in both cases you're not passing structures, you're passing a pointer. It just happens that the first example is an uninitialized pointer and the second points to something we KNOW we own. There is a third possibility which you did not present as an example (but which I believe you are confusing things with), namely: struct stat sbuf; lstat("/unix", sbuf); Now, this is simply wrong because most system calls deal in pointers or other scalar types, and not structures passed by value. It's possibly that a compiler which implements structure passing by passing pointers would cause this example to "work", but it seems irrelevant to me, and incorrect for entirely different reasons than the ones you are trying to propose. >In any case, the second method (passing &sbuf) IS portable and is standard. >This is NOT, however, picked up by lint... Most lints would say "sbuf may be used before set" in your first example IFF you didn't initialize it. But if you DID initialize it, even if you initialized it to NULL, lint would no longer catch it. lint carries no semantics which tells it that some initialization values are OK and others aren't. >PS: This program was a port from VaxC, which ran it with no problem. It was > and old piece of code which I did very quick-and-dry... So what? The VAX is one of the architectures which allows you to trash location 0. >PPS: I understand C quite well thank you... It doesn't seem so. I would be very wary of taking a device driver written by someone who exhibits the kind of misunderstanding of pointers which you have here. This is not a personal dig, just a reasonable observation. -- Steve Dyer dyer@ursa-major.spdcc.com aka {ima,harvard,rayssd,linus,m2c}!spdcc!dyer dyer@arktouros.mit.edu, dyer@hstbme.mit.edu
jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) (09/18/90)
In article <4062@ursa-major.SPDCC.COM> dyer@ursa-major.spdcc.com.spdcc.COM (Steve Dyer) writes: > >>PPS: I understand C quite well thank you... > >It doesn't seem so. > >I would be very wary of taking a device driver written by someone who >exhibits the kind of misunderstanding of pointers which you have here. >This is not a personal dig, just a reasonable observation. > >-- FLAME ON: Okay. so it was a friday and I was tired and I wrote a posting before I stopped to see what the hell I was writing. True, I was trying to save face with all this crap about compilers and so forth. However, these were observations from myself, others and assembler code from 3 different compilers running through this self same code. Some compilers WON'T let you pass structures to functions as is canon K&R. Some compilers WILL, when you tell the pointer to point to NULL, have the pointer point to space which is big enuff for whatever the pointer is a pointer to. This is a fact. What the problem was was that I was looking at the code without THINKING about the code... I guess someone as perfect as you has never done THAT before. As far as you thinking I don't understand C, well, I beg to differ. Everyone has off days with C and can't recall what they wrote or what they mean, except of course yourself. I've written a bunch of C code, dude and it hasn't been all 100% perfect, but no one's is, except yours, of course. I can't wait till YOU make a mistake, so I can knock your ass down! PS: What device drivers are you talking about asshole? The EtherPortII drivers???????? THEY are from Kinetics... I simply tared them together and made them available to people... oh yeah, I DID happen to change a "BNET" to "bnet_dr" in the install script... Hope to hell I can use vi to your satisfaction! I could go on about you thinking that I wrote these drivers as being a stupid mistake, but I won't. FLAME OFF: Now, we return you to your regularly scheduled group... -- ======================================================================= #include <std/disclaimer.h> =:^) Jim Jagielski NASA/GSFC, Code 711.1 jim@jagmac2.gsfc.nasa.gov Greenbelt, MD 20771 "Kilimanjaro is a pretty tricky climb. Most of it's up, until you reach the very, very top, and then it tends to slope away rather sharply."
liam@cs.qmw.ac.uk (William Roberts) (09/21/90)
In <3434@dftsrv.gsfc.nasa.gov> jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) writes: >In article <4062@ursa-major.SPDCC.COM> dyer@ursa-major.spdcc.com.spdcc.COM (Steve Dyer) writes: >> > Some compilers WON'T let > you pass structures to functions as is canon K&R. True, but not particularly relevant. Such a compiler should be associated with a version of lint that also insists on this, and none of your examples did this anyway. > Some compilers WILL, > when you tell the pointer to point to NULL, have the pointer point to > space which is big enuff for whatever the pointer is a pointer to. This is > a fact. Hang on a minute - name one such compiler! You were the one who started talking about "canon K&R" and XJwhatever committee numbers. > What the problem was was that I was looking at the code without > THINKING about the code... I guess someone as perfect as you has never done > THAT before. As far as you thinking I don't understand C, well, I beg to > differ. Everyone has off days with C and can't recall what they wrote or > what they mean, except of course yourself. I've written a bunch of C code, > dude and it hasn't been all 100% perfect, but no one's is, except yours, > of course. Your making the EtherPort II stuff available is appreciated (I may soon have something to add to your distribution - we have 50 of the old EtherPort II cards so I am putting work into making they coexist with A/UX 2.0 as well as possible). Your flame about the mild criticisms your pointer-confusion has earned is wildly out of proportion. You cannot both quote ANSI documents AND say that "some compilers do ***horrid thing omitted***". Do you now accept that 1) the stat and lstat functions require a pointer to a statbuf structure 2) the stat and lstat functions don't do memory allocation for that structure 3) NULL is not a good choice of random address for a structure 4) You should be using &statbuf regardless of the fact that some compiler/machine/architecture combinations let you get away with what you were doing before. Making mistakes is forgiveable - insisting that they aren't mistakes is not. -- William Roberts ARPA: liam@cs.qmw.ac.uk Queen Mary & Westfield College UUCP: liam@qmw-cs.UUCP Mile End Road AppleLink: UK0087 LONDON, E1 4NS, UK Tel: 071-975 5250 (Fax: 081-980 6533)
jim@jagmac2.gsfc.nasa.gov (Jim Jagielski) (09/23/90)
In article <2842@sequent.cs.qmw.ac.uk> liam@cs.qmw.ac.uk (William Roberts) writes: >Do you now accept that > >1) the stat and lstat functions require a pointer to a statbuf structure >2) the stat and lstat functions don't do memory allocation for that structure >3) NULL is not a good choice of random address for a structure >4) You should be using &statbuf regardless of the fact that some > compiler/machine/architecture combinations let you get away with > what you were doing before. > As I wrote to Steve, yes I DID make a major mistake: 1st by passing the wrong thing to stat and lstat and secondly NOT accepting the obvious reason for the mistake... that the reason it DIDN'T work with cc and gcc is because stuff was getting crunched since the pointer either pointed somewhere unknown or to NULL (0). That is in essense what the entire thing was about... My other comments about how stuff was being changed by different compilers was really not appropriate, since even if it DID work with some other compilers, that still doesn't affect the fact that the code was plain and simple WRONG. The only thing that reall upset me was the comment concerning my knowledge of C and that's what caused my flame... a bruised ego is a dangerous thing and I am sorry for that. Everyone makes mistakes and I just didn't want a stupid one to give the impression that I don't know C (although at the time, maybe my mind was such mush that I didn't even know my name :). Anyway, I hope all this is over with. I made my peace and apologies to Steve and appreciate all his ( and everyone else's) comments and illumination. The moral is: Think before you act... I gotta start doing that MORE! -- ======================================================================= #include <std/disclaimer.h> =:^) Jim Jagielski NASA/GSFC, Code 711.1 jim@jagmac2.gsfc.nasa.gov Greenbelt, MD 20771 "Kilimanjaro is a pretty tricky climb. Most of it's up, until you reach the very, very top, and then it tends to slope away rather sharply."