rse         99/11/28 05:51:54

  Modified:    src      CHANGES
               src/ap   ap_snprintf.c
  Log:
  Fixed `quad integer' (aka `long long') handling in ap_snprintf.c
  More details were described in my original posting two weeks ago:
  
  -----------------------------------------------------------------------
  Today (on my birthday ;) I've hacked on and cleaned up snprintf
  implementations for a forthcoming string library and discovered the following
  bug in ap_snprintf.  If one tries to print a "long long" value which is just a
  little bit lower than the maximimum "unsigned long" (not "unsigned long
  long"!) value, ap_snprintf treats the value as a (signed) "long" instead of a
  "long long":
  
  | $ cat test.c
  | #include <stdio.h>
  | #include "ap_config.h"
  | #include "ap.h"
  |
  | int main(int argc, char *argv[])
  | {
  |     char buf[1024];
  |
  |     ap_snprintf(buf, sizeof(buf), "%qd %qd", 4294967290ULL, 4294967297ULL);
  |     printf("ap_snprintf: \"%s\"\n", buf);
  |
  |     sprintf(buf, "%qd %qd", 4294967290ULL, 4294967297ULL);
  |     printf("sprintf:     \"%s\"\n", buf);
  | }
  | $ cc -I../os/unix -I../include -o test test.c libap.a && ./test
  | ap_snprintf: "-6 4294967297"
  | sprintf:     "4294967290 4294967297"
  
  The reason is a wrong optimization test in ap_snprintf.c which
  can be fixed this way:
  
  Index: ap_snprintf.c
  ===================================================================
  RCS file: /e/apache/REPOS/apache-1.3/src/ap/ap_snprintf.c,v
  retrieving revision 1.37
  diff -u -r1.37 ap_snprintf.c
  --- ap_snprintf.c   1999/10/21 20:44:10 1.37
  +++ ap_snprintf.c   1999/11/17 12:22:11
  @@ -414,7 +413,7 @@
        * If the value is less than the maximum unsigned long value,
        * then we know we aren't using quads, so use the faster function
        */
  -    if (num <= ULONG_MAX)
  +    if (num <= ULONG_MAX && is_unsigned)
          return(conv_10( (wide_int)num, is_unsigned, is_negative,
             buf_end, len));
  
  With this patch ap_snprintf and the (FreeBSD) vendor sprintf print the same
  values:
  
  | $ cc -I../os/unix -I../include -o test test.c libap.a && ./test
  | ap_snprintf: "4294967290 4294967297"
  | sprintf:     "4294967290 4294967297"
  
  I think the patch is correct, although I have to admit that because of time
  I've not checked the whole quad-fiddling in ap_snprintf.c now. So I do not
  commit this myself. Instead someone else should review this first.
  -----------------------------------------------------------------------
  
  Revision  Changes    Path
  1.1460    +3 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1459
  retrieving revision 1.1460
  diff -u -r1.1459 -r1.1460
  --- CHANGES   1999/11/28 13:37:50     1.1459
  +++ CHANGES   1999/11/28 13:51:49     1.1460
  @@ -1,5 +1,8 @@
   Changes with Apache 1.3.10
   
  +  *) Fixed `quad integer' (aka `long long') handling in ap_snprintf.c
  +     [Ralf S. Engelschall]
  +
     *) Fixed error handling in dbmmanage script.
        [Andrew McRae <[EMAIL PROTECTED]>] PR#4973
   
  
  
  
  1.38      +1 -1      apache-1.3/src/ap/ap_snprintf.c
  
  Index: ap_snprintf.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/ap/ap_snprintf.c,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -r1.37 -r1.38
  --- ap_snprintf.c     1999/10/21 20:44:10     1.37
  +++ ap_snprintf.c     1999/11/28 13:51:54     1.38
  @@ -414,7 +414,7 @@
        * If the value is less than the maximum unsigned long value,
        * then we know we aren't using quads, so use the faster function
        */
  -    if (num <= ULONG_MAX)
  +    if (num <= ULONG_MAX && is_unsigned)
        return(conv_10( (wide_int)num, is_unsigned, is_negative,
               buf_end, len));
   
  
  
  

Reply via email to