[2433] in Kerberos_V5_Development

home help back first fref pref prev next nref lref last post

Re: Unsigned ints and longs.... (sign expansion)

daemon@ATHENA.MIT.EDU (Ken Raeburn)
Tue Jul 15 13:29:29 1997

To: epeisach@MIT.EDU
Cc: krbdev@MIT.EDU
From: Ken Raeburn <raeburn@cygnus.com>
Date: 15 Jul 1997 13:28:36 -0400
In-Reply-To: epeisach@MIT.EDU's message of Mon, 14 Jul 1997 21:24:41 -0400

epeisach@MIT.EDU writes:

> This is a problem on the Alpha's using the current source tree
> (krb51.0pl1 + changes):

You describe different behavior in the call, but not the actual
problem this causes.  Do you get incorrect messages back from
error_message?

> The problem stems from the fact that we are trying to overload the
> minor status return code from the gssapi level (which is an unsigned
> interger) with a krb5 error, which is a long.

The error code needs 32 bits.  ANSI C guarantees that "int" has at
least 16, and "long" at least 32.  So com_err was set up to use a
"long".  (Perhaps it should've been "unsigned long".)  The com_err
code ought to be consistent in its treatment of the upper bits, though
I don't know if it is, and it may be requiring that the application is
also (which would be reasonable but probably not necessary).

That you're converting between "long" and a narrower type means you're
breaking the abstraction a bit, and can expect to have to work around
it.

> The following problem in from lib/gssapi/generic/disp_com_err_status.c
> and with GCC 2.7.2.2 Dec OSF 4.0A. The native C compiler does not have
> this problem. In the last release, I had patched the com_err library
> to do something to I believe work around this problem which in
> retrospect was not so kosher, which Richard has changed part of the NT
> port. I believe that the com_err library is correct in its behavior at
> the moment.

What was the problem with the com_err patch?  (What was the patch?)
One obvious work-around seems to me to make com_err ignore anything
above the lowest 32 bits.

Or, "knowing" how the com_err values are handled, convert status_value
to a signed 32-bit type (by cast or assignment) before treating it as
a krb5 error code.

> The problem:
> 
> We have:
> OM_uint32
> g_display_com_err_status(minor_status, status_value, status_string)
>      OM_uint32 *minor_status;
>      OM_uint32 status_value;
>      gss_buffer_t status_string;
> 
> So far so good, but then we have:
> 
>    if (! g_make_string_buffer(((status_value == 0)?no_error:
> 			       error_message(status_value)),
> 			      status_string)) {
> 
> error_message is prototyped to take a long as an argument. 
> 
> Now, if status is a negative value (i.e. any good ol fashioned krb5
> error code), it appears that gcc is calling error_message with what
> appears to be a positive long value (essentially positive of the krb5
> error). 

With the prototype, the uint32 value needs to be widened to long.  So,
assuming "uint32" is "unsigned int", zero-extending is the right thing
to do.  If it were converted to a signed 32-bit type first, it should
be sign-extended.  If the native compiler doesn't work this way, at
least under ANSI mode, it's buggy.

> If the prototype for error_message is removed, then the negative value
> is being passed on down. (I suspect gcc assumes that error_message
> takes an unsigned int in absence of information).

Actually, it's supposed to assume "usual integral promotions", which
means unsigned int doesn't change.  However, I think 32-bit values are
always passed around sign-extended to 64 under gcc on the Alpha.

> What I believe is happening is that gcc being smart, expects an
> unsigned int, and wants to convert it to a long. I may be wrong about
> this. How do I track down if either gcc is wrong, cc is wrong, or we
> are doing something wrong. I think this may be a difficiency in the C
> binding for the gssapi layer, or in our use of it.

If the function expects a long, and the code passes an int, and
there's no prototype, the code is wrong.

The real bug is the use of a 32-bit type to carry a value coming from
an interface that uses "long" (and apparently, from your troubles,
*not* "low 32 bits of a long").  You could consider it a deficiency of
GSSAPI's C bindings that it forces you to do so.

Someday, I'd like to see a *real* error reporting system, capable of
reporting errors with auxiliary data (e.g., name of file not found),
severity levels, chained errors (e.g., this high-level error was
caused by this low-level error), etc.  But that would take real work.

home help back first fref pref prev next nref lref last post