From: MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX" 24-OCT-1992 01:46:51.02 To: info-vax@sri.com CC: davis@amy.tch.harvard.edu Subj: known VAXCRTL bugs A week or two ago, I wrote: >> VAXCRTL has lots of bugs... [but getenv's memory consumption wasn't one] In a comp.os.vms article that took a long time to finally get to Info-VAX, John E Davis asks: > What are they? I am really interested since I do alot of programming in > VAX C. Is there a list anywhere? I imagine Digital has a list. ;-) The V5.5-2 Release Notes describe a bunch of fixes: several math routines apparently weren't detecting errors and/or setting `errno' properly; the socket routines had various bugs; scanw() didn't handle EOF correctly; longjmp(0) didn't behave as documented. Most of the others things are included in my list below. An observation: a substantial percentage of these bugs occur in modules written in Macro32 rather than C. I suspect that DECC$SHR won't/doesn't have much assembler code in it. (After VMS V5.*, VAXCRTL appears to become a shadow of its former self, mostly just a stub to interface with DECC$SHR.) This is the list of things either I've encountered or helped others investigate or seen others report and then confirmed for myself. Many of them could be fixed by just inserting a single C statement or even a single assembler instruction into the code. VAXCRTL.EXE should be easily patchable, but VAXCRTL.OLB then poses a problem... I have test cases for a lot of them, and have run those under V5.5-2HW and T6.0-5J9 (oops; can't reveal that :-). I haven't gotten around to checking some of the things near the end of the list. Compiler version has absolutely nothing to do with these (except for _CTYPE_); they are bugs in the run-time library shipped with VMS. One likely reason they've taken so long to get fixed is that people tend to report them (incorrectly) as compiler bugs instead of as VMS bugs. ===== Known problems with VMS's C run-time library, VAXCRTL, still present in VMS V5.5. [Fixes for many are finally appearing...] qsort -- once you sort something with size that's a multiple of 4 and longword aligned, trying to sort something else which is not a multiple of 4 or not longword aligned will risk corrupting the data since exchanges will move the wrong number of bytes. [this is known to affect GNU C on VMS; it relies on qsort] {fixed in 5.5-2} strncat -- trying to copy M bytes out of a string of length M+N where N is greater than or equal to 65535 will result in it getting stuck in an infinite loop. [this affects gcc-cpp, the GNU C pre-processor; size and current contents of destination buffer make no difference] {fixed in 5.5-2} realloc -- if the first argument is NULL, the results are unpredictable. A pair of registers are left uninitialized in that case, then they're used to try to copy the contents of the old memory block into the newly allocated one. ACCVIO or silent data corruption is possible; benign if register R5 happens to be 0. {fixed in 6.0} VAXC$REALLOC_OPT -- returns garbage (whatever happens to be in register R0) when the first argument is NULL. {fixed in 6.0} puts("") -- will output one byte of junk (duplicated from previous output) if--and only if--writing to a terminal. The problem only occurs when an empty string is passed and only affects output to terminal devices, not disk files, mailboxes, &c. Work-around: #define puts(foo) (fputs((foo),stdout),fputc('\n',stdout)) {fixed in 6.0} getenv("PATH") -- if there's a logical name or symbol called PATH defined, its value will be used instead of the current directory [that's documented]; however, it won't be properly '\0' terminated and the internal value of one of the other environment values will end up implicitly concatenated to it. {fixed in 6.0} getenv("TERM") -- returns "unknown" for VT420, even though VT400_Series has been supported by VMS since V5.4. Work-around: keep your terminal in VT320 mode... {fixed in 6.0} raise -- missing from VAXCRTL even though it's been documented since VMS V4.6 and VAX C V2.3; work-around: #define raise gsignal {fixed in 6.0} setbuf/setvbuf -- end-of-file not always set properly for stream_lf files (and probably the other two stream formats) if a buffer larger than 512 is used. [CSC may have a patch available for this] {5.5-2 release notes state that this is fixed} open(...,O_WRONLY|O_CREAT|O_TRUNC,...) -- if a new version of an existing file is created [which is how O_TRUNC is documented to work], the modification and expiration dates of the old file will be updated even though it isn't really touched, and the new version of the file will inherit the old one's creation date instead of the current date [this could be argued as a feature, but it occurs as an accidental side-effect of the RMS calls used and is inconsistent with other VMS file behavior]. {fixed in 6.0} printf("%g") -- chooses %e format instead of %f for values in the range of 1e-2 to 1e-4, contrary to both the documentation (%f would give shorter result) and the ANSI standard. {fixed in 6.0} _CTYPE_ -- the character type macros in only handle args in the range 0 thru 127, when -1 thru 255 (EOF plus 0 thru 255) should be supported. The toupper() and tolower() library functions handle 0 to 255 correctly [for ASCII, not the ISO Latin or DEC Multinational character sets], but change EOF (-1) to 255. [6.0 appears to have all the required `ctype' library routines] chdir -- the optional [undocumented/unsupported?] second argument (for requesting a change that persists after the program exits) does not not work; it correctly calls lib$set_logical instead of sys$crelnm in order to create a supervisor mode logical definition for sys$disk, but the constructed arguments are bad and it fails with an invalid string descriptor status; the result is that the directory component of the default directory ends up changed, but the device component remains unchanged. [Under T6.0-5J9, it falsely claims successful completion but still fails to set the default device.] sys_errlist[] -- this publicly accessible array of error message text has only 35+1 elements, but the size reported in the corresponding `sys_nerr' variable claims that it has 65+1, resulting in risk of ACCVIO in programs that rely on it. The internal array of messages used by strerror() actually does have all 65 elements. {fixed in 6.0, sort of; sys_nerr is set to the truncated count of 35} VAXC$ESTABLISH -- requires that the caller set aside the longword at the top of the _caller's_ stack frame (at address @FP-4) for its private use. This is handled automatically by VAX C and is documented (paraphrased: "only use it from VAX C, as it relies on an allocation on the run-time stack") but is easy to overlook. Failure to provide this ``hidden local variable'' can result in an access violation inside VAXCRTL's condition handling code when dealing with any condition other than C$_LONGJMP, at the time it tries to invoke the user-specified handler. [GNU CC deaks with this situation correctly in version 2.2 and up for gcc 2.x and version 1.41 and up for gcc 1.x.] {not a bug, just a potential "gotcha"} strerror -- if the first argument is EVMSERR and the optional second argument is omitted, it will return a null pointer rather than something sensible like "VMS-specific error". [However, it does not ACCVIO as previously claimed.] {not a bug; could/should be improved} execvp -- concatenates "VAXC$PATH:" with caller's file_name argument and passes that on to execve(); however, it does not properly '\0' terminate the constructed filename string so intermittent strange errors from LIB$SPAWN() are possible. mktime -- present in both vaxcrtl.olb and vaxcrtl.exe, but not documented strftime -- also not documented, present in vaxcrtl.olb but inaccessible from vaxcrtl.exe. [Both functions appear to work correctly.] setlocale, localeconv -- locale support not [yet?] implemented mb*, wc* -- multi-byte/wide-character support not [yet?] implemented {not bugs} Older bugs of note: difftime -- subtracts smaller arg from larger rather than first from second. {fixed in 5.4-3} =====