misc/83107: libc uuid_compare() doesn't work with large numbers

Steve Sears sjs at acm.org
Thu Jul 7 18:40:23 GMT 2005


>Number:         83107
>Category:       misc
>Synopsis:       libc uuid_compare() doesn't work with large numbers
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul 07 18:40:11 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Steve Sears
>Release:        5.4
>Organization:
self
>Environment:
FreeBSD sjs-linux.nane.netapp.com 5.4-STABLE FreeBSD 5.4-STABLE #19: Mon Apr 18 11:28:21 EDT 2005     root at sjs-linux.nane.netapp.com:/usr/src/sys-sjs/i386/compile/SJSKERN  i386

>Description:
      If you use uuid_compare and the uuid's are very different, an int
is too small to contain the results. For example, according to this code:

865e1a56-b9d9-11d9-ba27-0003476f2e88 < 062ac45c-b9d9-11d9-ba27-0003476f2e88

The implementation takes the results of a subtraction of the numbers
and assigns it to an int. But if the high bits remain on after the
subtraction, an int is too small and the results are negative.

The routine is located at ./src/lib/libc/uuid/uuid_compare.c

>How-To-Repeat:
      Invoke uuid_compare with the above two numbers. 

>Fix:
      Very simple fix: in uuid_compare.c, uuid_compare(), change the
local variable 'res' from int to int64_t. Remove the '(int)' cast from
the first subtraction.

Cdiff follows:

=== /u/sjs/freebsd/usr/src/lib/libc/uuid/uuid_compare.c ====
***************
*** 41,47 ****
  int32_t
  uuid_compare(uuid_t *a, uuid_t *b, uint32_t *status)
  {
!       int res;
  
        if (status != NULL)
                *status = uuid_s_ok;
--- 41,47 ----
  int32_t
  uuid_compare(uuid_t *a, uuid_t *b, uint32_t *status)
  {
!       int64_t res;
  
        if (status != NULL)
                *status = uuid_s_ok;
***************
*** 55,61 ****
                return ((uuid_is_nil(a, NULL)) ? 0 : 1);
  
        /* We have to compare the hard way. */
!       res = (int)((int64_t)a->time_low - (int64_t)b->time_low);
        if (res)
                return ((res < 0) ? -1 : 1);
        res = (int)a->time_mid - (int)b->time_mid;
--- 55,61 ----
                return ((uuid_is_nil(a, NULL)) ? 0 : 1);
  
        /* We have to compare the hard way. */
!       res = (int64_t)a->time_low - (int64_t)b->time_low;
        if (res)
                return ((res < 0) ? -1 : 1);
        res = (int)a->time_mid - (int)b->time_mid;

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list