Samba 2.2.2 problem in lib/sprintf.c

John E. Malmberg malmberg at adelphia.net
Sat Dec 1 17:45:01 GMT 2001


Andrew Tridgell wrote:
 > John Malmberg wrote:

>>The original code has proven to be broken on several platforms, and
>>will not build.  Either the compiler optimizer dies, or the resulting 
>>object modules will not link.
>>
> 
> the optimiser dies?!? That's a little hard to believe. Is the compiler
> on your system that broken? Link failures are also surprising.


That version of the compiler apparently had a bug, where it did not 
properly diagnose the condition where it was given conflicting instructions.


> 
> no, it's that many systems have broken snprintf() implementations. The
> C99 standard specifies some very specific behaviour that Samba now
> relies on (for very good reasons). Some systems don't follow that
> standard. We replace snprintf on those systems.


I understand that an existing snprintf() implementation may be broken.

One issue is that the configure test that Martin Pool posted is 
defective.  Without the prototypes, or compiler dependent flags, it is 
not really testing if the implementation has a broken snprintf.

What it is really testing is for an implementation that had a broken 
snprintf in the past, the compiler can still generate code to call that 
broken snprintf for applications that may be depend on the broken behavior.

The shortcut of skipping putting standard headers on a test program can 
very well invalidate it's results.

So until a fixed test is done, you may not know if the snprintf() is 
broken on a platform.


> 
>>Many systems will not allow a global procedure name conflict with one 
>>that is supplied in a standard library.  It produces a duplicate symbol 
>>conflict at link time.
>>
> 
> !?! then your linker is badly broken.


No, that is expected and well documented behavior when the standard 
library is in a shared image.

When you link against a shared image, you get all of the symbols.  So if 
you have named a global routine in a module the same as one in the 
library, that is a duplicate symbol violation.

This may not be signaled with all linkers.  But even on the systems 
where it is not signaled, depending on which symbol is used in some 
cases may be unreliable.


> Can you try the following simple
> program:
 
> #include <sys/types.h>
> 
> int snprintf(char *str, size_t size, const  char  *format, ...)
> {
> 	return 0;
> }
> 
> main()
> {
> 	return snprintf("foo", 0, 0);
> }
> 
> and see if it compiles. It should on any system. It won't give the
> same answer on all systems, but it should *always* compile.



EAGLE> cc tridge_snprintf.c/standard=ansi89

int snprintf(char *str, size_t size, const  char  *format, ...)
....^
%CC-I-INTRINSICDECL, In this statement, the declaration for intrinsic 
function snprintf" referenced at line number 10 in file 
PROJECT_ROOT:[SAMBA_VMS.SOURCE.TESTS]TRIDGE_SNPRINTF.C;1, the body of 
the function is being defined.  It will be treated as an ordinary 
external function.
at line number 3 in file 
PROJECT_ROOT:[SAMBA_VMS.SOURCE.TESTS]TRIDGE_SNPRINTF.C


Version T6.5 of the Compaq C compiler appears to have been fixed to 
diagnose the problem and report it correctly.

The code "-I-" in the diagnostic indicates that it is for 
"Informational" purposes only.

But when the snprintf() routine is in a separate module, and the 
standard header is used, then the intrinsic function will be used by the 
  compiler for the other modules.

So even though you have provided a replacement routine, none of the 
other modules will ever call it.  No diagnostic is required to inform 
the programmer of this.


>>If samba wants to supply it's own replacement routines for standard 
>>library calls, I recommend changing the name of the routines to have 
>>unique symbols like smb_snprintf() so that there is never a conflict 
>>with existing symbols in a standard library.
>>
> 
> we only do this when we absolutely have to. It is better to replace
> the broken function where possible.


I agree that a broken function needs to be replaced.  The issue is the 
way to do it that is portable, and will always produce the expected results.

The same is true when supplying missing routines.  A unique prefix 
should be applied.

Changing case to make a global symbol is allowed by the C standard, but 
is should be avoided.  While I can set the OpenVMS linking environment 
to be case sensitive on the global symbols, the default is to be case 
insensitive.

But the real reason to use prefixes like smb_ is that it is more obvious 
to a human that a different routine is desired.  A name with the wrong 
case does not stand out as well.

And if you decide to add in a third party library, a prefix is less 
likely to collide with any symbol creativity that they may have done.

Example: Realloc() in the UBIQX library caused a conflict SAMBA code 
written from before the UBIQX library was inserted.  This is documented 
in the comments in the source code.


> show me the compiler output from the above test program. Then maybe we
> can work out how to fix it. If we need to use a macro we will, but I
> would like to know why.


Because it is the only way that will produce reliable results on all 
platforms.



> I find it hard to believe that the above simple program won't

> compile on any system that is even vaguely POSIX.


Compile yes, but not without diagnostics.  If I drop back to 
/STANDARD=C89, the diagnostic does not appear.



I have asked before if there were specific coding standards that SAMBA 
is attempting to be compliant with.

There are several places where I have to override the compiler 
diagnostics because of issues where the SAMBA source code is not 
compliant with one of the C standards that also prevents it building on 
OpenVMS.

I usually only report the ones here that I know can affect other 
platforms than OpenVMS.

Normally I use the default settings, plus turning up the warning level 
to assist in finding programming errors.

Basically for this version of the compiler, it will diagnose violations 
of C99, and also will diagnose many questionable coding practices.


And inspite of what I am writting below, SAMBA for it's size is 
remarkably clean for GNU software in the quantity and quality of the 
diagnostics that are generated when I compile it.

It does not compile cleanly though.  Several of the diagnostic messages 
are from ANSI violations that the GCC compiler documents that it will 
allow with out diagnosis regardless of the warning level set.

But not everyone uses GCC.  And that does not cover all of the diagnostics.

 From reading this list for the past couple of years it is apparent that 
the SAMBA team does care about portability and having SAMBA compile clean.


But if you can name the standard that you are following, I will set my 
build environment to match, and then I can report the diagnostics that 
are flagged, usually with a patch that will eliminate it, as it is not 
worth my time to produce a report until I can get my build to complete 
with out diagnostics.


For example, with C90, global symbols must be unique within the first 31 
characters.  There are a few global symbols in SAMBA that fail that 
requirement.

This requirement may not be enforced on platforms other than OpenVMS, 
but it can also result in duplicate global symbols.

Since the other linkers also do not report duplicate global symbols, if 
they also have this limitation, it will only show up when the programs 
encounter the bad code at runtime.

Since I have not seen any reports of those type of bugs, I am assuming 
that of the platforms running SAMBA that OpenVMS is the only one that is 
affected.  Of course those are symbols like:

make_spoolss_q_getprinterdriver2
make_spoolss_q_getprinterdriverdir

If the wrong routine was called on some platform, it obviously would 
have been noticed by now, wouldn't it?


-John
wb8tyw at qsl.network
Personal Opinion Only





More information about the samba-technical mailing list