Sfoglia il codice sorgente

Don't rely on integer wrapping in ctype

Don't rely on integer wrapping in ctype and fix strcasecmp on
non-alphabetic characters
jD91mZM2 6 anni fa
parent
commit
1c92751a73
3 ha cambiato i file con 14 aggiunte e 10 eliminazioni
  1. 9 9
      src/header/ctype/mod.rs
  2. 2 1
      src/header/strings/mod.rs
  3. 3 0
      tests/strings.c

+ 9 - 9
src/header/ctype/mod.rs

@@ -24,27 +24,27 @@ pub extern "C" fn isblank(c: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn iscntrl(c: c_int) -> c_int {
-    ((c as c_uint) < 0x20 || c == 0x7f) as c_int
+    (c < 0x20 || c == 0x7f) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isdigit(c: c_int) -> c_int {
-    (((c - 0x30) as c_uint) < 10) as c_int
+    (c >= b'0' as c_int && c <= b'9' as c_int) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isgraph(c: c_int) -> c_int {
-    (((c - 0x21) as c_uint) < 0x5e) as c_int
+    (c >= 0x21 && c < 0x7e) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn islower(c: c_int) -> c_int {
-    (((c - 0x61) as c_uint) < 26) as c_int
+    (c >= b'a' as c_int && c <= b'z' as c_int) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isprint(c: c_int) -> c_int {
-    (((c - 0x20) as c_uint) < 0x5f) as c_int
+    (c >= 0x20 && c < 0x7f) as c_int
 }
 
 #[no_mangle]
@@ -59,12 +59,12 @@ pub extern "C" fn isspace(c: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn isupper(c: c_int) -> c_int {
-    (((c - 0x41) as c_uint) < 26) as c_int
+    (c >= b'A' as c_int && c <= b'Z' as c_int) as c_int
 }
 
 #[no_mangle]
 pub extern "C" fn isxdigit(c: c_int) -> c_int {
-    (isdigit(c) != 0 || ((c as c_int) | 32) - ('a' as c_int) < 6) as c_int
+    (isdigit(c) != 0 || (c | 32 >= b'a' as c_int && c | 32 <= 'f' as c_int)) as c_int
 }
 
 #[no_mangle]
@@ -77,7 +77,7 @@ pub extern "C" fn toascii(c: c_int) -> c_int {
 #[no_mangle]
 pub extern "C" fn tolower(c: c_int) -> c_int {
     if isupper(c) != 0 {
-        c + 0x20
+        c | 0x20
     } else {
         c
     }
@@ -86,7 +86,7 @@ pub extern "C" fn tolower(c: c_int) -> c_int {
 #[no_mangle]
 pub extern "C" fn toupper(c: c_int) -> c_int {
     if islower(c) != 0 {
-        c - 0x20
+        c & !0x20
     } else {
         c
     }

+ 2 - 1
src/header/strings/mod.rs

@@ -2,6 +2,7 @@
 
 use core::ptr;
 
+use header::ctype;
 use platform::types::*;
 
 #[no_mangle]
@@ -76,7 +77,7 @@ pub unsafe extern "C" fn strncasecmp(
     mut n: size_t,
 ) -> c_int {
     while n > 0 && (*first != 0 || *second != 0) {
-        let cmp = (*first & !32) as c_int - (*second & !32) as c_int;
+        let cmp = ctype::tolower(*first as c_int) - ctype::tolower(*second as c_int);
         if cmp != 0 {
             return cmp;
         }

+ 3 - 0
tests/strings.c

@@ -22,6 +22,9 @@ int main() {
     assert(strncasecmp("FLOOR0_1", "FLOOR0_1FLOOR4_1", 8) == 0);
     assert(strncasecmp("FL00RO_1", "FLOOR0_1FLOOR4_1", 8) < 0);
 
+    // Ensure we aren't relying on the 5th (lowercase) bit on non-alpha characters
+    assert(strcasecmp("{[", "[{") > 0);
+
     bzero(new, 1);
     assert(*new == 0);
     assert(*(new+1) == 'i');