Samba 2.2.2 problem in lib/sprintf.c

John E. Malmberg wb8tyw at qsl.net
Fri Nov 30 04:44:04 GMT 2001


Martin Pool wrote:

 > On 27 Nov 2001, "John E. Malmberg" <wb8tyw at qsl.net> wrote:
 >
 >> An optimizing C compiler, especially on a RISC platform has
 >> intimate  knowledge of the standard library routines, and will
 >> attempt to  eliminate procedure calls where ever possible.  If
 >> you are supplying  your own routines, their definition can not
 >> exist in a header file that  is #included for the module.  That
 >> breaks things.
 >>
 >
 > Almost every compiler that plays this kind of trick has a
 > command-line option that disables them.  For example, on gcc it is
 > -fno-builtin. So perhaps you just need to set that, or better yet
 > contribute a configure.in test that detects the problem and sets it
 >  into CFLAGS.


You really do not want to disable the feature.  It basically is turning
off major optimizations.

 > On the other hand, if the compiler's so good then I'd hope that
 > the sprintf() is properly compliant with the ANSI C99 standard.
 > The test for that in ./configure on samba_2_2 is currently
 >
 > #include <sys/types.h
 > #include <stdarg.h
 > void foo(const char *format, ...)
 > {
 >  va_list ap; int len; char buf[5];
 >
 >  va_start(ap, format);
 >  len = vsnprintf(0, 0, format, ap);
 >  va_end(ap);
 >
 > if (len != 5)
 >     exit(1);
 >
 > if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0)
 >    exit(1);
 >
 > exit(0);
 > }
 > main()
 > { foo("hello"); }
 >
 > It would be interesting to see the result of this on your compiler.


I plan to install the latest field test this weekend.

But the configure test is already broken.  If the header file is not 
#included, the compiler may assume (unless you override it with compiler 
flags) that you do want it to fall back to an older version of the 
snprintf() routine in the standard library.  Thus the test will produce 
a false failure.

 > Also, if there is something in <stdio.h> that invokes the magic
 > behaviour, then perhaps you should try adding it to the test code
 > in configure.in.
 >

You basically must always prototype everything if you are testing
compliance, or you must know the particular flags to force compliance
with a compiler.  You simply can not leave anything ambiguous.

Any configure test that is missing header files will produce suspect
results.  And because the product using the results works around it,
many times the issue is never seen, unless someone is investigating an
optimization issue for their platform.


 > However if the intrinsic version works and the library version is
 > broken then we have a nasty situation, because I think the compiler
 > will sometimes fall back to a library call for complex cases.
 > So then we come back to needing the equivalent of -fno-builtin.


Consider that once a an operating system releases a run-time library, 
end-users have qualified it, the entry point in the shared image that 
the routine uses must not change name or it's vector.

And the compiler vendor can get a lot of flack it the end users must
make radical changes to their build scripts because of the change.

The best compromise for the compiler vendor to make is to assume code 
with out standard headers wants to be compliant with the older behavior, 
and that code with standard headers wants to be compliant with the 
current standard.

Therefore the default settings for the compiler may not be ones that are 
strictly standard compliant.

If an update for a standard changes the behavior for a run-time library 
function, then the way to do it with out breaking compatability is to 
either provide a new shared image, which is inefficient, or a new entry 
point with a new name.

Because of all of this, all standard library routine names must be 
treated as reserved words to application programs.

Using standard library routine names a local routines, or as function 
pointers in a structure will cause the compile to break on many 
compilers.  Cases have shown up on this list for platforms other than 
OpenVMS.

The safest thing to do is to give replacement routines a prefix to 
prevent namespace collisions.

Also if you are putting a wrapper arround a library routine, if an 
architecture can implement that routine as a builtin, you are 
introducing a performance hit for that architecture.

If this is in time critical code, the cumulative effect may be noticable.

And also if a linker is not complaining about duplicate symbols, than 
depending on implementation options, you really do not know if your 
replacement routine or the wrapper routine is being used by the code at 
the target sites.

You only know for the platforms that you have explicitly tested.

-John
wb8tyw at qsl.network
Personal Opinion Only





More information about the samba-technical mailing list