8194667: Regex: Serialization doesn't work with match flags

Reviewed-by: rriggs
This commit is contained in:
Xueming Shen 2018-01-12 14:05:42 -08:00
parent fb8bca78ee
commit b69a95d78d
2 changed files with 55 additions and 31 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -953,6 +953,12 @@ public final class Pattern
*/ */
private int flags; private int flags;
/**
* The temporary pattern flags used during compiling. The flags might be turn
* on and off by embedded flag.
*/
private transient int flags0;
/** /**
* Boolean indicating this Pattern is compiled; this is necessary in order * Boolean indicating this Pattern is compiled; this is necessary in order
* to lazily compile deserialized Patterns. * to lazily compile deserialized Patterns.
@ -1137,7 +1143,7 @@ public final class Pattern
* @return The match flags specified when this pattern was compiled * @return The match flags specified when this pattern was compiled
*/ */
public int flags() { public int flags() {
return flags; return flags0;
} }
/** /**
@ -1369,6 +1375,9 @@ public final class Pattern
// Read in all fields // Read in all fields
s.defaultReadObject(); s.defaultReadObject();
// reset the flags
flags0 = flags;
// Initialize counts // Initialize counts
capturingGroupCount = 1; capturingGroupCount = 1;
localCount = 0; localCount = 0;
@ -1400,6 +1409,9 @@ public final class Pattern
if ((flags & UNICODE_CHARACTER_CLASS) != 0) if ((flags & UNICODE_CHARACTER_CLASS) != 0)
flags |= UNICODE_CASE; flags |= UNICODE_CASE;
// 'flags' for compiling
flags0 = flags;
// Reset group index count // Reset group index count
capturingGroupCount = 1; capturingGroupCount = 1;
localCount = 0; localCount = 0;
@ -1841,7 +1853,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
* Indicates whether a particular flag is set or not. * Indicates whether a particular flag is set or not.
*/ */
private boolean has(int f) { private boolean has(int f) {
return (flags & f) != 0; return (flags0 & f) != 0;
} }
/** /**
@ -2718,7 +2730,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
ch == 0x53 || ch == 0x73 || //S and s ch == 0x53 || ch == 0x73 || //S and s
ch == 0x4b || ch == 0x6b || //K and k ch == 0x4b || ch == 0x6b || //K and k
ch == 0xc5 || ch == 0xe5))) { //A+ring ch == 0xc5 || ch == 0xe5))) { //A+ring
bits.add(ch, flags()); bits.add(ch, flags0);
return null; return null;
} }
return single(ch); return single(ch);
@ -2931,7 +2943,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
boolean capturingGroup = false; boolean capturingGroup = false;
Node head = null; Node head = null;
Node tail = null; Node tail = null;
int save = flags; int save = flags0;
int saveTCNCount = topClosureNodes.size(); int saveTCNCount = topClosureNodes.size();
root = null; root = null;
int ch = next(); int ch = next();
@ -3032,7 +3044,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
} }
accept(')', "Unclosed group"); accept(')', "Unclosed group");
flags = save; flags0 = save;
// Check for quantifiers // Check for quantifiers
Node node = closure(head); Node node = closure(head);
@ -3135,28 +3147,28 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
for (;;) { for (;;) {
switch (ch) { switch (ch) {
case 'i': case 'i':
flags |= CASE_INSENSITIVE; flags0 |= CASE_INSENSITIVE;
break; break;
case 'm': case 'm':
flags |= MULTILINE; flags0 |= MULTILINE;
break; break;
case 's': case 's':
flags |= DOTALL; flags0 |= DOTALL;
break; break;
case 'd': case 'd':
flags |= UNIX_LINES; flags0 |= UNIX_LINES;
break; break;
case 'u': case 'u':
flags |= UNICODE_CASE; flags0 |= UNICODE_CASE;
break; break;
case 'c': case 'c':
flags |= CANON_EQ; flags0 |= CANON_EQ;
break; break;
case 'x': case 'x':
flags |= COMMENTS; flags0 |= COMMENTS;
break; break;
case 'U': case 'U':
flags |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE); flags0 |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE);
break; break;
case '-': // subFlag then fall through case '-': // subFlag then fall through
ch = next(); ch = next();
@ -3178,28 +3190,28 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
for (;;) { for (;;) {
switch (ch) { switch (ch) {
case 'i': case 'i':
flags &= ~CASE_INSENSITIVE; flags0 &= ~CASE_INSENSITIVE;
break; break;
case 'm': case 'm':
flags &= ~MULTILINE; flags0 &= ~MULTILINE;
break; break;
case 's': case 's':
flags &= ~DOTALL; flags0 &= ~DOTALL;
break; break;
case 'd': case 'd':
flags &= ~UNIX_LINES; flags0 &= ~UNIX_LINES;
break; break;
case 'u': case 'u':
flags &= ~UNICODE_CASE; flags0 &= ~UNICODE_CASE;
break; break;
case 'c': case 'c':
flags &= ~CANON_EQ; flags0 &= ~CANON_EQ;
break; break;
case 'x': case 'x':
flags &= ~COMMENTS; flags0 &= ~COMMENTS;
break; break;
case 'U': case 'U':
flags &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE); flags0 &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE);
break; break;
default: default:
return; return;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,7 @@
* 8027645 8035076 8039124 8035975 8074678 6854417 8143854 8147531 7071819 * 8027645 8035076 8039124 8035975 8074678 6854417 8143854 8147531 7071819
* 8151481 4867170 7080302 6728861 6995635 6736245 4916384 6328855 6192895 * 8151481 4867170 7080302 6728861 6995635 6736245 4916384 6328855 6192895
* 6345469 6988218 6693451 7006761 8140212 8143282 8158482 8176029 8184706 * 6345469 6988218 6693451 7006761 8140212 8143282 8158482 8176029 8184706
* 8194667
* *
* @library /test/lib * @library /test/lib
* @build jdk.test.lib.RandomFactory * @build jdk.test.lib.RandomFactory
@ -1367,24 +1368,35 @@ public class RegExTest {
report("Reluctant Repetition"); report("Reluctant Repetition");
} }
private static Pattern serializedPattern(Pattern p) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(p);
oos.close();
try (ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray()))) {
return (Pattern)ois.readObject();
}
}
private static void serializeTest() throws Exception { private static void serializeTest() throws Exception {
String patternStr = "(b)"; String patternStr = "(b)";
String matchStr = "b"; String matchStr = "b";
Pattern pattern = Pattern.compile(patternStr); Pattern pattern = Pattern.compile(patternStr);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); Pattern serializedPattern = serializedPattern(pattern);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(pattern);
oos.close();
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray()));
Pattern serializedPattern = (Pattern)ois.readObject();
ois.close();
Matcher matcher = serializedPattern.matcher(matchStr); Matcher matcher = serializedPattern.matcher(matchStr);
if (!matcher.matches()) if (!matcher.matches())
failCount++; failCount++;
if (matcher.groupCount() != 1) if (matcher.groupCount() != 1)
failCount++; failCount++;
pattern = Pattern.compile("a(?-i)b", Pattern.CASE_INSENSITIVE);
serializedPattern = serializedPattern(pattern);
if (!serializedPattern.matcher("Ab").matches())
failCount++;
if (serializedPattern.matcher("AB").matches())
failCount++;
report("Serialization"); report("Serialization");
} }