# HG changeset patch # User igerasim # Date 1559094953 25200 # Tue May 28 18:55:53 2019 -0700 # Node ID c5c9afc62f7d9ceffab1f396154edefebe041dd9 # Parent d850d0f41c7227afd2f89d1aa58a5a03cb2636ea 8224789: Parsing repetition count in regex does not detect numeric overflow Reviewed-by: rriggs, bchristi diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -3271,28 +3271,33 @@ case '+': return curly(prev, 1); case '{': - ch = temp[cursor+1]; + ch = skip(); if (ASCII.isDigit(ch)) { - skip(); - int cmin = 0; - do { - cmin = cmin * 10 + (ch - '0'); - } while (ASCII.isDigit(ch = read())); - int cmax = cmin; - if (ch == ',') { - ch = read(); - cmax = MAX_REPS; - if (ch != '}') { - cmax = 0; - while (ASCII.isDigit(ch)) { - cmax = cmax * 10 + (ch - '0'); - ch = read(); + int cmin = 0, cmax; + try { + do { + cmin = Math.addExact(Math.multiplyExact(cmin, 10), + ch - '0'); + } while (ASCII.isDigit(ch = read())); + cmax = cmin; + if (ch == ',') { + ch = read(); + cmax = MAX_REPS; + if (ch != '}') { + cmax = 0; + while (ASCII.isDigit(ch)) { + cmax = Math.addExact(Math.multiplyExact(cmax, 10), + ch - '0'); + ch = read(); + } } } + } catch (ArithmeticException ae) { + throw error("Illegal repetition range"); } if (ch != '}') throw error("Unclosed counted closure"); - if (((cmin) | (cmax) | (cmax - cmin)) < 0) + if (cmax < cmin) throw error("Illegal repetition range"); Curly curly; ch = peek(); diff --git a/test/jdk/java/util/regex/RegExTest.java b/test/jdk/java/util/regex/RegExTest.java --- a/test/jdk/java/util/regex/RegExTest.java +++ b/test/jdk/java/util/regex/RegExTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ * 8027645 8035076 8039124 8035975 8074678 6854417 8143854 8147531 7071819 * 8151481 4867170 7080302 6728861 6995635 6736245 4916384 6328855 6192895 * 6345469 6988218 6693451 7006761 8140212 8143282 8158482 8176029 8184706 - * 8194667 8197462 8184692 8221431 + * 8194667 8197462 8184692 8221431 8224789 * * @library /test/lib * @library /lib/testlibrary/java/lang @@ -44,15 +44,28 @@ * @key randomness */ -import java.util.function.Function; -import java.util.regex.*; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.nio.CharBuffer; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Random; import java.util.Scanner; -import java.io.*; -import java.nio.file.*; -import java.util.*; -import java.nio.CharBuffer; +import java.util.function.Function; import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.MatchResult; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import jdk.test.lib.RandomFactory; /** @@ -171,6 +184,7 @@ grapheme(); expoBacktracking(); invalidGroupName(); + illegalRepetitionRange(); if (failure) { throw new @@ -4932,4 +4946,31 @@ } report("Invalid capturing group names"); } + + private static void illegalRepetitionRange() { + // huge integers > (2^31 - 1) + String n = BigInteger.valueOf(1L << 32) + .toString(); + String m = BigInteger.valueOf(1L << 31) + .add(new BigInteger(80, generator)) + .toString(); + for (String rep : List.of("", "x", ".", ",", "-1", "2,1", + n, n + ",", "0," + n, n + "," + m, m, m + ",", "0," + m)) { + String pat = ".{" + rep + "}"; + try { + Pattern.compile(pat); + failCount++; + System.out.println("Expected to fail. Pattern: " + pat); + } catch (PatternSyntaxException e) { + if (!e.getMessage().startsWith("Illegal repetition")) { + failCount++; + System.out.println("Unexpected error message: " + e.getMessage()); + } + } catch (Throwable t) { + failCount++; + System.out.println("Unexpected exception: " + t); + } + } + report("illegalRepetitionRange"); + } }