Skip to content

Commit ee97592

Browse files
committed
Fix exception handling in parseInt, parseLong
Previously these were directly interpreted by jbmc before exception checking, meaning you could crash jbmc by passing a constant radix '37' for example.
1 parent 31df88c commit ee97592

File tree

3 files changed

+27
-87
lines changed

3 files changed

+27
-87
lines changed

src/main/java/java/lang/Integer.java

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -410,51 +410,7 @@ public static int parseInt(String s, int radix)
410410
" greater than Character.MAX_RADIX");
411411
}
412412

413-
if (radix == 10) {
414-
return parseInt(s);
415-
}
416-
417-
//TODO from here on
418-
int result = 0;
419-
boolean negative = false;
420-
int i = 0, len = s.length();
421-
int limit = -Integer.MAX_VALUE;
422-
int multmin;
423-
int digit;
424-
425-
if (len > 0) {
426-
char firstChar = CProverString.charAt(s, 0);
427-
if (firstChar < '0') { // Possible leading "+" or "-"
428-
if (firstChar == '-') {
429-
negative = true;
430-
limit = Integer.MIN_VALUE;
431-
} else if (firstChar != '+')
432-
throw NumberFormatException.forInputString(s);
433-
434-
if (len == 1) // Cannot have lone "+" or "-"
435-
throw NumberFormatException.forInputString(s);
436-
i++;
437-
}
438-
multmin = limit / radix;
439-
while (i < len) {
440-
// Accumulating negatively avoids surprises near MAX_VALUE
441-
digit = Character.digit(CProverString.charAt(s, i++), radix);
442-
if (digit < 0) {
443-
throw NumberFormatException.forInputString(s);
444-
}
445-
if (result < multmin) {
446-
throw NumberFormatException.forInputString(s);
447-
}
448-
result *= radix;
449-
if (result < limit + digit) {
450-
throw NumberFormatException.forInputString(s);
451-
}
452-
result -= digit;
453-
}
454-
} else {
455-
throw NumberFormatException.forInputString(s);
456-
}
457-
return negative ? result : -result;
413+
return CProverString.parseInt(s, radix);
458414
}
459415

460416
/**
@@ -475,7 +431,11 @@ public static int parseInt(String s, int radix)
475431
* parsable integer.
476432
*/
477433
public static int parseInt(String s) throws NumberFormatException {
478-
return CProver.nondetInt(); //The function is handled by cbmc internally
434+
if (s == null) {
435+
throw new NumberFormatException("null");
436+
}
437+
438+
return CProverString.parseInt(s, 10);
479439
}
480440

481441
/**

src/main/java/java/lang/Long.java

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -474,46 +474,7 @@ public static long parseLong(String s, int radix)
474474
" greater than Character.MAX_RADIX");
475475
}
476476

477-
long result = 0;
478-
boolean negative = false;
479-
int i = 0, len = s.length();
480-
long limit = -Long.MAX_VALUE;
481-
long multmin;
482-
int digit;
483-
484-
if (len > 0) {
485-
char firstChar = CProverString.charAt(s, 0);
486-
if (firstChar < '0') { // Possible leading "+" or "-"
487-
if (firstChar == '-') {
488-
negative = true;
489-
limit = Long.MIN_VALUE;
490-
} else if (firstChar != '+')
491-
throw NumberFormatException.forInputString(s);
492-
493-
if (len == 1) // Cannot have lone "+" or "-"
494-
throw NumberFormatException.forInputString(s);
495-
i++;
496-
}
497-
multmin = limit / radix;
498-
while (i < len) {
499-
// Accumulating negatively avoids surprises near MAX_VALUE
500-
digit = Character.digit(CProverString.charAt(s, i++), radix);
501-
if (digit < 0) {
502-
throw NumberFormatException.forInputString(s);
503-
}
504-
if (result < multmin) {
505-
throw NumberFormatException.forInputString(s);
506-
}
507-
result *= radix;
508-
if (result < limit + digit) {
509-
throw NumberFormatException.forInputString(s);
510-
}
511-
result -= digit;
512-
}
513-
} else {
514-
throw NumberFormatException.forInputString(s);
515-
}
516-
return negative ? result : -result;
477+
return CProverString.parseLong(s, radix);
517478
}
518479

519480
/**
@@ -541,7 +502,10 @@ public static long parseLong(String s, int radix)
541502
* parsable {@code long}.
542503
*/
543504
public static long parseLong(String s) throws NumberFormatException {
544-
return CProver.nondetLong(); //The function is handled by cbmc internally
505+
if (s == null) {
506+
throw new NumberFormatException("null");
507+
}
508+
return CProverString.parseLong(s, 10);
545509
}
546510

547511
/**

src/main/java/org/cprover/CProverString.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,4 +440,20 @@ public static String toString(float f) {
440440
public static String toString(double d) {
441441
return toString(CProver.doubleToFloat(d));
442442
}
443+
444+
/**
445+
* Exactly as Integer.parseInt, except s is already checked non-null and the
446+
* radix is already checked in-range.
447+
*/
448+
public static int parseInt(String s, int radix) {
449+
return CProver.nondetInt();
450+
}
451+
452+
/**
453+
* Exactly as Long.parseLong, except s is already checked non-null and the
454+
* radix is already checked in-range.
455+
*/
456+
public static long parseLong(String s, int radix) {
457+
return CProver.nondetLong();
458+
}
443459
}

0 commit comments

Comments
 (0)