[ruby-oci8-commit] [377] trunk/ruby-oci8: * ext/oci8/ocinumber.c, ext/oci8/oranumber_util.c,

nobody at rubyforge.org nobody at rubyforge.org
Sun Feb 7 07:52:15 EST 2010


Revision: 377
Author:   kubo
Date:     2010-02-07 07:52:15 -0500 (Sun, 07 Feb 2010)

Log Message:
-----------
* ext/oci8/ocinumber.c, ext/oci8/oranumber_util.c,
  ext/oci8/oranumber_util.h: change the declaration of
    oranumber_to_str() to prevent buffer overflow by
    unexpected invalid Oracle number internal data.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/ocinumber.c
    trunk/ruby-oci8/ext/oci8/oranumber_util.c
    trunk/ruby-oci8/ext/oci8/oranumber_util.h

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-02-07 10:02:22 UTC (rev 376)
+++ trunk/ruby-oci8/ChangeLog	2010-02-07 12:52:15 UTC (rev 377)
@@ -1,4 +1,10 @@
 2010-02-07  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/ocinumber.c, ext/oci8/oranumber_util.c,
+	  ext/oci8/oranumber_util.h: change the declaration of
+	    oranumber_to_str() to prevent buffer overflow by
+	    unexpected invalid Oracle number internal data.
+
+2010-02-07  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/error.c, ext/oci8/oci8.h: add oci8_raise_by_msgno()
 	    to retrieve a Oracle error message which depends on NLS_LANGUAGE.
 	* ext/oci8/oranumber_util.c, ext/oci8/oranumber_util.h,

Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocinumber.c	2010-02-07 10:02:22 UTC (rev 376)
+++ trunk/ruby-oci8/ext/oci8/ocinumber.c	2010-02-07 12:52:15 UTC (rev 377)
@@ -123,12 +123,12 @@
         return LONG2NUM(sl);
     }
     /* convert to Integer via String */
-    rv = oranumber_to_str(s, buf);
+    rv = oranumber_to_str(s, buf, sizeof(buf));
     if (rv > 0) {
         return rb_cstr2inum(buf, 10);
     }
     oranumber_dump(s, buf);
-    rb_raise(eOCIException, "Could not convert OraNumber(%s) to string", buf);
+    rb_raise(eOCIException, "Invalid internal number format: %s", buf);
 }
 
 VALUE oci8_make_float(OCINumber *s, OCIError *errhp)
@@ -1026,10 +1026,12 @@
 
     rb_scan_args(argc, argv, "02", &fmt /* nil */, &nls_params /* nil */);
     if (NIL_P(fmt)) {
-        rv = oranumber_to_str(_NUMBER(self), buf);
+        rv = oranumber_to_str(_NUMBER(self), buf, sizeof(buf));
         if (rv > 0) {
             return rb_usascii_str_new(buf, rv);
         }
+        oranumber_dump(_NUMBER(self), buf);
+        rb_raise(eOCIException, "Invalid internal number format: %s", buf);
     }
     StringValue(fmt);
     fmt_ptr = RSTRING_ORATEXT(fmt);

Modified: trunk/ruby-oci8/ext/oci8/oranumber_util.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oranumber_util.c	2010-02-07 10:02:22 UTC (rev 376)
+++ trunk/ruby-oci8/ext/oci8/oranumber_util.c	2010-02-07 12:52:15 UTC (rev 377)
@@ -3,7 +3,7 @@
 #include <string.h>
 #include "oranumber_util.h"
 
-int oranumber_to_str(const OCINumber *on, char *buf)
+int oranumber_to_str(const OCINumber *on, char *buf, int buflen)
 {
     signed char exponent;
     signed char mantissa[21]; /* terminated by a negative number */
@@ -11,6 +11,20 @@
     int len = 0;
     int idx;
     int n;
+#define PUTC(chr) do { \
+    if (len < buflen) { \
+        buf[len++] = (chr); \
+    } else { \
+        return ORANUMBER_TOO_SHORT_BUFFER; \
+    } \
+} while(0)
+#define PUTEND() do { \
+    if (len < buflen) { \
+        buf[len] = '\0'; \
+    } else { \
+        return ORANUMBER_TOO_SHORT_BUFFER; \
+    } \
+} while(0)
 
     if (datalen == 0) {
         /* too short */
@@ -19,8 +33,8 @@
     if (datalen == 1) {
         if (on->OCINumberPart[1] == 0x80) {
             /* zero */
-            buf[0] = '0';
-            buf[1] = '\0';
+            PUTC('0');
+            PUTEND();
             return 1;
         }
         /* unexpected format */
@@ -45,7 +59,7 @@
             mantissa[idx] = 101 - on->OCINumberPart[idx + 2];
         }
         mantissa[idx] = -1;
-        buf[len++] = '-';
+        PUTC('-');
     }
     /* convert exponent and mantissa to human readable number */
     idx = 0;
@@ -53,43 +67,43 @@
         /* integer part */
         n = mantissa[idx++];
         if (n / 10 != 0) {
-            buf[len++] = n / 10 + '0';
+            PUTC(n / 10 + '0');
         }
-        buf[len++] = n % 10 + '0';
+        PUTC(n % 10 + '0');
         while (exponent-- >= 0) {
             n = mantissa[idx++];
             if (n < 0) {
                 do {
-                    buf[len++] = '0';
-                    buf[len++] = '0';
+                    PUTC('0');
+                    PUTC('0');
                 } while (exponent-- >= 0);
-                buf[len] = '\0';
+                PUTEND();
                 return len;
             }
-            buf[len++] = n / 10 + '0';
-            buf[len++] = n % 10 + '0';
+            PUTC(n / 10 + '0');
+            PUTC(n % 10 + '0');
         }
         if (mantissa[idx] < 0) {
-            buf[len] = '\0';
+            PUTEND();
             return len;
         }
     } else {
-        buf[len++] = '0';
+        PUTC('0');
     }
-    buf[len++] = '.';
+    PUTC('.');
     /* fractional number part */
     while (++exponent < -1) {
-        buf[len++] = '0';
-        buf[len++] = '0';
+        PUTC('0');
+        PUTC('0');
     }
     while ((n = mantissa[idx++]) >= 0) {
-        buf[len++] = n / 10 + '0';
-        buf[len++] = n % 10 + '0';
+        PUTC(n / 10 + '0');
+        PUTC(n % 10 + '0');
     }
     if (buf[len - 1] == '0') {
         len--;
     }
-    buf[len] = '\0';
+    PUTEND();
     return len;
 }
 

Modified: trunk/ruby-oci8/ext/oci8/oranumber_util.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oranumber_util.h	2010-02-07 10:02:22 UTC (rev 376)
+++ trunk/ruby-oci8/ext/oci8/oranumber_util.h	2010-02-07 12:52:15 UTC (rev 377)
@@ -8,11 +8,14 @@
 #define ORANUMBER_UTIL_H 1
 #include <orl.h>
 
+#define ORANUMBER_INVALID_INTERNAL_FORMAT -1
+#define ORANUMBER_TOO_SHORT_BUFFER -2
+
 #define ORANUMBER_SUCCESS 0
 #define ORANUMBER_INVALID_NUMBER 1722
 #define ORANUMBER_NUMERIC_OVERFLOW 1426
 
-int oranumber_to_str(const OCINumber *on, char *buf);
+int oranumber_to_str(const OCINumber *on, char *buf, int buflen);
 int oranumber_from_str(OCINumber *on, const char *buf, int buflen);
 
 #define ORANUMBER_DUMP_BUF_SIZ 99




More information about the ruby-oci8-commit mailing list