HHH-13259 Fix StackOverflowError in StringHelper
Before fix method org.hibernate.internal.util.StringHelper#replace matched placeholders illegally in case when ordinal parameters list was expanded. Ex. placeholder ?1 was matched with ?11, ?12, ?13 etc. For queries with 2 or more IN clauses with different collections there were a situation when ?1 from the first clause matched with already expanded placeholders from the second collection. Each match led to recursive call of replace method. If collection in second clause was very long then StackOverflowError occurred. Fix adds check of partial placeholder match for wholeWords mode which is used in expanding list parameters. Partial matches are skipped during replace.
This commit is contained in:
parent
fed93b0ae9
commit
35037dac7b
|
@ -123,7 +123,7 @@ public final class StringHelper {
|
|||
if ( template == null ) {
|
||||
return null;
|
||||
}
|
||||
int loc = template.indexOf( placeholder );
|
||||
int loc = indexOfPlaceHolder( template, placeholder, wholeWords );
|
||||
if ( loc < 0 ) {
|
||||
return template;
|
||||
}
|
||||
|
@ -189,6 +189,24 @@ public final class StringHelper {
|
|||
return buf.toString();
|
||||
}
|
||||
|
||||
private static int indexOfPlaceHolder(String template, String placeholder, boolean wholeWords) {
|
||||
if ( wholeWords ) {
|
||||
int placeholderIndex = -1;
|
||||
boolean isPartialPlaceholderMatch;
|
||||
do {
|
||||
placeholderIndex = template.indexOf( placeholder, placeholderIndex + 1 );
|
||||
isPartialPlaceholderMatch = placeholderIndex != -1 &&
|
||||
template.length() > placeholderIndex + placeholder.length() &&
|
||||
Character.isJavaIdentifierPart( template.charAt( placeholderIndex + placeholder.length() ) );
|
||||
} while ( placeholderIndex != -1 && isPartialPlaceholderMatch );
|
||||
|
||||
return placeholderIndex;
|
||||
}
|
||||
else {
|
||||
return template.indexOf( placeholder );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find the ordinal parameters (e.g. '?1') in a string.
|
||||
*/
|
||||
|
|
|
@ -100,4 +100,24 @@ public class StringHelperTest extends BaseUnitTestCase {
|
|||
Assert.assertFalse( StringHelper.isQuoted( "a", sqlServerDialect ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceRepeatingPlaceholdersWithoutStackOverflow() {
|
||||
String ordinalParameters = generateOrdinalParameters( 3, 19999 );
|
||||
String result = StringHelper.replace(
|
||||
"select * from books where category in (?1) and id in(" + ordinalParameters + ") and parent_category in (?1) and id in(" + ordinalParameters + ")",
|
||||
"?1", "?1, ?2", true, true );
|
||||
assertEquals( "select * from books where category in (?1, ?2) and id in(" + ordinalParameters + ") and parent_category in (?1, ?2) and id in(" + ordinalParameters + ")", result );
|
||||
}
|
||||
|
||||
private String generateOrdinalParameters(int startPosition, int endPosition) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for ( int i = startPosition; i <= endPosition; i++ ) {
|
||||
builder.append( '?' ).append( i );
|
||||
if ( i < endPosition ) {
|
||||
builder.append( ", " );
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue