@@ -1901,7 +1901,11 @@ vim_str2nr(
19011901 n += 2 ; /* skip over "0b" */
19021902 while ('0' <= * ptr && * ptr <= '1' )
19031903 {
1904- un = 2 * un + (unsigned long )(* ptr - '0' );
1904+ /* avoid ubsan error for overflow */
1905+ if (un < UVARNUM_MAX / 2 )
1906+ un = 2 * un + (unsigned long )(* ptr - '0' );
1907+ else
1908+ un = UVARNUM_MAX ;
19051909 ++ ptr ;
19061910 if (n ++ == maxlen )
19071911 break ;
@@ -1912,7 +1916,11 @@ vim_str2nr(
19121916 /* octal */
19131917 while ('0' <= * ptr && * ptr <= '7' )
19141918 {
1915- un = 8 * un + (uvarnumber_T )(* ptr - '0' );
1919+ /* avoid ubsan error for overflow */
1920+ if (un < UVARNUM_MAX / 8 )
1921+ un = 8 * un + (uvarnumber_T )(* ptr - '0' );
1922+ else
1923+ un = UVARNUM_MAX ;
19161924 ++ ptr ;
19171925 if (n ++ == maxlen )
19181926 break ;
@@ -1925,7 +1933,11 @@ vim_str2nr(
19251933 n += 2 ; /* skip over "0x" */
19261934 while (vim_isxdigit (* ptr ))
19271935 {
1928- un = 16 * un + (uvarnumber_T )hex2nr (* ptr );
1936+ /* avoid ubsan error for overflow */
1937+ if (un < UVARNUM_MAX / 16 )
1938+ un = 16 * un + (uvarnumber_T )hex2nr (* ptr );
1939+ else
1940+ un = UVARNUM_MAX ;
19291941 ++ ptr ;
19301942 if (n ++ == maxlen )
19311943 break ;
@@ -1936,7 +1948,11 @@ vim_str2nr(
19361948 /* decimal */
19371949 while (VIM_ISDIGIT (* ptr ))
19381950 {
1939- un = 10 * un + (uvarnumber_T )(* ptr - '0' );
1951+ /* avoid ubsan error for overflow */
1952+ if (un < UVARNUM_MAX / 10 )
1953+ un = 10 * un + (uvarnumber_T )(* ptr - '0' );
1954+ else
1955+ un = UVARNUM_MAX ;
19401956 ++ ptr ;
19411957 if (n ++ == maxlen )
19421958 break ;
@@ -1950,9 +1966,19 @@ vim_str2nr(
19501966 if (nptr != NULL )
19511967 {
19521968 if (negative ) /* account for leading '-' for decimal numbers */
1953- * nptr = - (varnumber_T )un ;
1969+ {
1970+ /* avoid ubsan error for overflow */
1971+ if (un > VARNUM_MAX )
1972+ * nptr = VARNUM_MIN ;
1973+ else
1974+ * nptr = - (varnumber_T )un ;
1975+ }
19541976 else
1977+ {
1978+ if (un > VARNUM_MAX )
1979+ un = VARNUM_MAX ;
19551980 * nptr = (varnumber_T )un ;
1981+ }
19561982 }
19571983 if (unptr != NULL )
19581984 * unptr = un ;
0 commit comments