[openssl-users] crypto/objects/o_names.c problem with Solaris 10 and strict Oracle Studio 12.6 c99

Michael Wojcik Michael.Wojcik at microfocus.com
Fri Jan 18 01:25:10 UTC 2019


> From: openssl-users [mailto:openssl-users-bounces at openssl.org] On Behalf Of
> Dennis Clarke
> Sent: Thursday, January 17, 2019 18:23
>
> "crypto/objects/o_names.c", line 114: error: undefined symbol: strcasecmp
> "crypto/objects/o_names.c", line 114: warning: improper pointer/integer
> combination: op "="
> "crypto/objects/o_names.c", line 151: warning: implicit function
> declaration: strcasecmp

Note the issue here is an undefined symbol, which consequently has an implicit definition as an int with external linkage and static duration. So we're talking about a header problem, not a library problem.

> So would love to hear someones thoughts on why strcasecmp suddenly went
> missing?

Well...

strcasecmp is a heresy. The C specification (ISO 9899) does not include strcasecmp, and reserves all identifiers with external linkage beginning with "str" for the library.

The *correct* way to do case-insensitive string comparisons in C is to write your own using the ctype.h functions (though it's tricky to get this right, due to the signed-char Undefined Behavior problem), with a name that doesn't infringe on a reserved part of the namespace. Or use a library which provides the same.

Unfortunately, strcasecmp was invented before C was standardized (as part of the BSD 4.something implementation, maybe?), and consequently gained too much traction to ever go away. Then it was standardized by XPG4, just to make things more difficult. And thus it's part of the Single UNIX Specification, even though the SUS has language about not conflicting with ISO 9899. Everyone just looks the other way and whistles quietly to themselves when they come across it.

*Consequently*, under Open Group Base Specifications Issue 7 (the latest version of SUS), to get a definition for strcasecmp you have to include <strings.h>. Note the second "s". <string.h> is the ISO C header for things like strcmp; <strings.h> is the SUS header for strcasecmp and other look-like-standard-C-but-aren't string functions. There's no way anyone would ever confuse the two.

Normally, the Solaris headers (at least for 10.2, which is what I'm logged into at the moment) include string.h in strings.h and vice versa, to hide this abomination from the eyes of the innocent. But those inclusions are wrapped in all manner of ifdeffery which I am not about to try to untangle.

Now, we see in the output you included in your note that you are getting strings.h in o_names.c. So that should be OK, yes?

But of course the declaration of strcasecmp in strings.h is itself ifdeffed. To get it, _XPG4_2 must be defined, and __EXTENSIONS__ must NOT be defined.

My guess is you're falling foul of one of those two conditions, when you compile in strict mode.

The simplest fix would be to whack a declaration of strcasecmp into the source file itself, but that's inelegant and hard to maintain - presumably you'd rather do something through the OpenSSL configure process. As for that, well... the only thing that comes to mind is something like:

1. Add -Dstrcasecmp=cmpstrci to the compiler flags
2. Add -lcmpstrci to the link flags
3. Create a little libcmpstrci.a (no need for it to be a shared object) with a case-insensitive string comparison function named cmpstrci. It can use strcasecmp if it must, or you can implement your own.

Or the problem might be something else, of course, but the fact that strings.h does appear in the output but strcasecmp isn't declared does suggest the conditional-compilation in strings.h is to blame.

--
Michael Wojcik
Distinguished Engineer, Micro Focus




More information about the openssl-users mailing list