There's a PR dealing with atof() problems: 
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17564>.

I think, we should simply avoid that function call.
The attached patch does the following:

- quality values are converted by a specialized function atoq.
- level values are no longer parsed as float (instead as int, using atoi). 
According to our documentation this was already intended :)

Do you see any problems with this patch? (especially with the level thing? 
(Does anybody actually use it?))

nd
-- 
package Hacker::Perl::Another::Just;print
[EMAIL PROTECTED] split/::/ =>__PACKAGE__]}~;

#  Andr� Malo  #  http://pub.perlig.de  #
Index: modules/mappers/mod_negotiation.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_negotiation.c,v
retrieving revision 1.113
diff -u -r1.113 mod_negotiation.c
--- modules/mappers/mod_negotiation.c   1 Mar 2003 23:57:32 -0000       1.113
+++ modules/mappers/mod_negotiation.c   9 Mar 2003 00:28:22 -0000
@@ -385,6 +385,65 @@
  */
 
 /*
+ * parse quality value. atof(3) is not well-usable here, because it
+ * depends on the locale (argh).
+ *
+ * However, RFC 2616 states:
+ * 3.9 Quality Values
+ *
+ * [...] HTTP/1.1 applications MUST NOT generate more than three digits
+ * after the decimal point. User configuration of these values SHOULD also
+ * be limited in this fashion.
+ *
+ *     qvalue         = ( "0" [ "." 0*3DIGIT ] )
+ *                    | ( "1" [ "." 0*3("0") ] )
+ *
+ * This is quite easy. If the supplied string doesn't match the above
+ * definition (loosely), we simply return 1 (same as if there's no qvalue)
+ */
+
+static float atoq(const char *string)
+{
+    if (!string || !*string) {
+        return  1.0f;
+    }
+
+    while (*string && apr_isspace(*string)) {
+        ++string;
+    }
+
+    /* be tolerant and accept qvalues without leading zero
+     * (also for backwards compat, where atof() was in use)
+     */
+    if (*string != '.' && *string++ != '0') {
+        return 1.0f;
+    }
+
+    if (*string == '.') {
+        /* better only one division later, than dealing with fscking
+         * IEEE format 0.1 factors ...
+         */
+        int i = 0;        
+
+        if (*++string > '0' && *string <= '9') {
+            i += (*string - '0') * 100;
+
+            if (*++string > '0' && *string <= '9') {
+                i += (*string - '0') * 10;
+
+                if (*++string > '0' && *string <= '9') {
+                    i += (*string - '0') * 1;
+                }
+            }
+        }
+
+        return (float)i / 1000.0f;
+    }
+
+    return 0.0f;
+}
+
+/*
  * Get a single mime type entry --- one media type and parameters;
  * enter the values we recognize into the argument accept_rec
  */
@@ -467,10 +526,10 @@
 
         if (parm[0] == 'q'
             && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) {
-            result->quality = (float)atof(cp);
+            result->quality = atoq(cp);
         }
         else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) {
-            result->level = (float)atof(cp);
+            result->level = (float)atoi(cp);
         }
         else if (!strcmp(parm, "charset")) {
             result->charset = cp;

Reply via email to