Ticket #13104: 01sscanfarithundef.patch
File 01sscanfarithundef.patch, 9.0 KB (added by , 5 years ago) 


src/common/util.c
diff git a/src/common/util.c b/src/common/util.c index 75dd6ed..ff1a371 100644
a b scan_unsigned(const char **bufp, unsigned long *out, int width, int base) 2837 2837 while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp)) 2838 2838 && scanned_so_far < width) { 2839 2839 int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++); 2840 unsigned long new_result = result * base + digit; 2841 if (new_result < result) 2842 return 1; /* over/underflow. */ 2843 result = new_result; 2840 // Check for overflow beforehand, without actually causing any overflow 2841 // This preserves functionality on compilers that don't wrap overflow 2842 // (i.e. that trap or optimise away overflow) 2843 // result * base + digit > ULONG_MAX 2844 // result * base > ULONG_MAX  digit 2845 if (result > (ULONG_MAX  digit)/base) 2846 return 1; /* Processing this digit would overflow */ 2847 result = result * base + digit; 2844 2848 ++scanned_so_far; 2845 2849 } 2846 2850 … … scan_signed(const char **bufp, long *out, int width) 2875 2879 if (scan_unsigned(bufp, &result, width, 10) < 0) 2876 2880 return 1; 2877 2881 2878 if (neg ) {2882 if (neg && result > 0) { 2879 2883 if (result > ((unsigned long)LONG_MAX) + 1) 2880 2884 return 1; /* Underflow */ 2881 *out = (long)result; 2885 // Avoid overflow on the cast to signed long when result is LONG_MIN 2886 // by subtracting 1 from the unsigned long positive value, 2887 // then, after it has been cast to signed and negated, 2888 // subtracting the original 1 (the doublesubtraction is intentional). 2889 // Otherwise, the cast to signed could cause a temporary long 2890 // to equal LONG_MAX + 1, which is undefined. 2891 // We avoid underflow on the subtraction by treating 0 as positive. 2892 *out = ((long)(result  1))  1; 2882 2893 } else { 2883 2894 if (result > LONG_MAX) 2884 2895 return 1; /* Overflow */ 
src/test/test_util.c
diff git a/src/test/test_util.c b/src/test/test_util.c index 1b7c936..005c91a 100644
a b static void 1688 1688 test_util_sscanf(void) 1689 1689 { 1690 1690 unsigned u1, u2, u3; 1691 unsigned long ulng; 1691 1692 char s1[20], s2[10], s3[10], ch; 1692 1693 int r; 1693 1694 long lng1,lng2; … … test_util_sscanf(void) 1729 1730 test_eq(0, tor_sscanf("", "%u", &u1)); /* absent number */ 1730 1731 test_eq(0, tor_sscanf("A", "%u", &u1)); /* bogus number */ 1731 1732 test_eq(0, tor_sscanf("1", "%u", &u1)); /* negative number */ 1732 test_eq(1, tor_sscanf("4294967295", "%u", &u1)); /* UINT32_MAX should work */1733 test_eq(4294967295u, u1);1734 test_eq(0, tor_sscanf("4294967296", "%u", &u1)); /* But not at 32 bits */1735 test_eq(1, tor_sscanf("4294967296", "%9u", &u1)); /* but parsing only 9... */1736 test_eq(429496729u, u1);1737 1733 1738 1734 /* Numbers with size (eg. %2u) */ 1739 1735 test_eq(0, tor_sscanf("1", "%2u", &u1)); … … test_util_sscanf(void) 1828 1824 test_eq(int2, 1); 1829 1825 1830 1826 #if SIZEOF_INT == 4 1827 /* %u */ 1828 /* UINT32_MAX should work */ 1829 test_eq(1, tor_sscanf("4294967295", "%u", &u1)); 1830 test_eq(4294967295U, u1); 1831 1832 /* But UINT32_MAX + 1 shouldn't work */ 1833 test_eq(0, tor_sscanf("4294967296", "%u", &u1)); 1834 /* but parsing only 9... */ 1835 test_eq(1, tor_sscanf("4294967296", "%9u", &u1)); 1836 test_eq(429496729U, u1); 1837 1838 /* %x */ 1839 /* UINT32_MAX should work */ 1840 test_eq(1, tor_sscanf("FFFFFFFF", "%x", &u1)); 1841 test_eq(0xFFFFFFFF, u1); 1842 1843 /* But UINT32_MAX + 1 shouldn't work */ 1844 test_eq(0, tor_sscanf("100000000", "%x", &u1)); 1845 1846 /* %d */ 1847 /* INT32_MIN and INT32_MAX should work */ 1831 1848 r = tor_sscanf("2147483648. 2147483647.", "%d. %d.", &int1, &int2); 1832 1849 test_eq(r,2); 1833 test_eq(int1, 2147483647 1);1850 test_eq(int1, 2147483647  1); 1834 1851 test_eq(int2, 2147483647); 1835 1852 1836 r = tor_sscanf("2147483679.", "%d.", &int1); 1853 /* But INT32_MIN  1 and INT32_MAX + 1 shouldn't work */ 1854 r = tor_sscanf("2147483649.", "%d.", &int1); 1837 1855 test_eq(r,0); 1838 1856 1839 r = tor_sscanf("2147483678.", "%d.", &int1); 1857 r = tor_sscanf("2147483648.", "%d.", &int1); 1858 test_eq(r,0); 1859 1860 /* and the first failure stops further processing */ 1861 r = tor_sscanf("2147483648. 2147483648.", 1862 "%d. %d.", &int1, &int2); 1863 test_eq(r,1); 1864 1865 r = tor_sscanf("2147483649. 2147483647.", 1866 "%d. %d.", &int1, &int2); 1867 test_eq(r,0); 1868 1869 r = tor_sscanf("2147483648. 2147483649.", 1870 "%d. %d.", &int1, &int2); 1840 1871 test_eq(r,0); 1841 1872 #elif SIZEOF_INT == 8 1873 /* %u */ 1874 /* UINT64_MAX should work */ 1875 test_eq(1, tor_sscanf("18446744073709551615", "%u", &u1)); 1876 test_eq(18446744073709551615U, u1); 1877 1878 /* But UINT64_MAX + 1 shouldn't work */ 1879 test_eq(0, tor_sscanf("18446744073709551616", "%u", &u1)); 1880 /* but parsing only 19... */ 1881 test_eq(1, tor_sscanf("18446744073709551616", "%19u", &u1)); 1882 test_eq(1844674407370955161U, u1); 1883 1884 /* %x */ 1885 /* UINT64_MAX should work */ 1886 test_eq(1, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1)); 1887 test_eq(0xFFFFFFFFFFFFFFFF, u1); 1888 1889 /* But UINT64_MAX + 1 shouldn't work */ 1890 test_eq(0, tor_sscanf("10000000000000000", "%x", &u1)); 1891 1892 /* %d */ 1893 /* INT64_MIN and INT64_MAX should work */ 1842 1894 r = tor_sscanf("9223372036854775808. 9223372036854775807.", 1843 1895 "%d. %d.", &int1, &int2); 1844 1896 test_eq(r,2); 1845 test_eq(int1, 9223372036854775807 1);1897 test_eq(int1, 9223372036854775807  1); 1846 1898 test_eq(int2, 9223372036854775807); 1847 1899 1900 /* But INT64_MIN  1 and INT64_MAX + 1 shouldn't work */ 1848 1901 r = tor_sscanf("9223372036854775809.", "%d.", &int1); 1849 1902 test_eq(r,0); 1850 1903 1851 1904 r = tor_sscanf("9223372036854775808.", "%d.", &int1); 1852 1905 test_eq(r,0); 1906 1907 /* and the first failure stops further processing */ 1908 r = tor_sscanf("9223372036854775808. 9223372036854775808.", 1909 "%d. %d.", &int1, &int2); 1910 test_eq(r,1); 1911 1912 r = tor_sscanf("9223372036854775809. 9223372036854775807.", 1913 "%d. %d.", &int1, &int2); 1914 test_eq(r,0); 1915 1916 r = tor_sscanf("9223372036854775808. 9223372036854775809.", 1917 "%d. %d.", &int1, &int2); 1918 test_eq(r,0); 1853 1919 #endif 1854 1920 1855 1921 #if SIZEOF_LONG == 4 1922 /* %lu */ 1923 /* UINT32_MAX should work */ 1924 test_eq(1, tor_sscanf("4294967295", "%lu", &ulng)); 1925 test_eq(4294967295UL, ulng); 1926 1927 /* But UINT32_MAX + 1 shouldn't work */ 1928 test_eq(0, tor_sscanf("4294967296", "%lu", &ulng)); 1929 /* but parsing only 9... */ 1930 test_eq(1, tor_sscanf("4294967296", "%9lu", &ulng)); 1931 test_eq(429496729UL, ulng); 1932 1933 /* %lx */ 1934 /* UINT32_MAX should work */ 1935 test_eq(1, tor_sscanf("FFFFFFFF", "%lx", &ulng)); 1936 test_eq(0xFFFFFFFFUL, ulng); 1937 1938 /* But UINT32_MAX + 1 shouldn't work */ 1939 test_eq(0, tor_sscanf("100000000", "%lx", &ulng)); 1940 1941 /* %ld */ 1942 /* INT32_MIN and INT32_MAX should work */ 1856 1943 r = tor_sscanf("2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2); 1857 1944 test_eq(r,2); 1858 test_eq(lng1, 2147483647  1); 1859 test_eq(lng2, 2147483647); 1945 test_eq(lng1, 2147483647L  1L); 1946 test_eq(lng2, 2147483647L); 1947 1948 /* But INT32_MIN  1 and INT32_MAX + 1 shouldn't work */ 1949 r = tor_sscanf("2147483649.", "%ld.", &lng1); 1950 test_eq(r,0); 1951 1952 r = tor_sscanf("2147483648.", "%ld.", &lng1); 1953 test_eq(r,0); 1954 1955 /* and the first failure stops further processing */ 1956 r = tor_sscanf("2147483648. 2147483648.", 1957 "%ld. %ld.", &lng1, &lng2); 1958 test_eq(r,1); 1959 1960 r = tor_sscanf("2147483649. 2147483647.", 1961 "%ld. %ld.", &lng1, &lng2); 1962 test_eq(r,0); 1963 1964 r = tor_sscanf("2147483648. 2147483649.", 1965 "%ld. %ld.", &lng1, &lng2); 1966 test_eq(r,0); 1860 1967 #elif SIZEOF_LONG == 8 1968 /* %lu */ 1969 /* UINT64_MAX should work */ 1970 test_eq(1, tor_sscanf("18446744073709551615", "%lu", &ulng)); 1971 test_eq(18446744073709551615UL, ulng); 1972 1973 /* But UINT64_MAX + 1 shouldn't work */ 1974 test_eq(0, tor_sscanf("18446744073709551616", "%lu", &ulng)); 1975 /* but parsing only 19... */ 1976 test_eq(1, tor_sscanf("18446744073709551616", "%19lu", &ulng)); 1977 test_eq(1844674407370955161UL, ulng); 1978 1979 /* %lx */ 1980 /* UINT64_MAX should work */ 1981 test_eq(1, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng)); 1982 test_eq(0xFFFFFFFFFFFFFFFFUL, ulng); 1983 1984 /* But UINT64_MAX + 1 shouldn't work */ 1985 test_eq(0, tor_sscanf("10000000000000000", "%lx", &ulng)); 1986 1987 /* %ld */ 1988 /* INT64_MIN and INT64_MAX should work */ 1861 1989 r = tor_sscanf("9223372036854775808. 9223372036854775807.", 1862 1990 "%ld. %ld.", &lng1, &lng2); 1863 1991 test_eq(r,2); 1864 test_eq(lng1, 9223372036854775807L  1 );1992 test_eq(lng1, 9223372036854775807L  1L); 1865 1993 test_eq(lng2, 9223372036854775807L); 1866 1994 1995 /* But INT64_MIN  1 and INT64_MAX + 1 shouldn't work */ 1996 r = tor_sscanf("9223372036854775809.", "%ld.", &lng1); 1997 test_eq(r,0); 1998 1999 r = tor_sscanf("9223372036854775808.", "%ld.", &lng1); 2000 test_eq(r,0); 2001 2002 /* and the first failure stops further processing */ 1867 2003 r = tor_sscanf("9223372036854775808. 9223372036854775808.", 1868 2004 "%ld. %ld.", &lng1, &lng2); 1869 2005 test_eq(r,1); 1870 r = tor_sscanf("9223372036854775809. 9223372036854775808.", 2006 2007 r = tor_sscanf("9223372036854775809. 9223372036854775807.", 2008 "%ld. %ld.", &lng1, &lng2); 2009 test_eq(r,0); 2010 2011 r = tor_sscanf("9223372036854775808. 9223372036854775809.", 1871 2012 "%ld. %ld.", &lng1, &lng2); 1872 2013 test_eq(r,0); 1873 2014 #endif