Skip to content

Commit b032e8a

Browse files
author
gitlab
committed
Merge branch 'fix-55163@@2' into '4.6.31'
<fix>[search]: escape special characters in API query conditions See merge request zstackio/zstack!3896
2 parents 0e75f9c + e66c4fd commit b032e8a

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

search/src/main/java/org/zstack/query/QueryFacadeImpl.java

+51-16
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.lang.reflect.Modifier;
4141
import java.util.*;
4242
import java.util.concurrent.TimeUnit;
43+
import java.util.function.IntConsumer;
4344
import java.util.stream.Collectors;
4445

4546
import static org.zstack.core.Platform.argerr;
@@ -387,20 +388,49 @@ private String toZQLConditionString(QueryCondition c) {
387388
if (c.getValue() == null) {
388389
return String.format("%s %s", c.getName(), c.getOp());
389390
} else if (op == QueryOp.IN || op == QueryOp.NOT_IN) {
390-
Set<String> values = new HashSet<>();
391-
for (String v : c.getValue().split(",")) {
392-
values.add(String.format("'%s'", v));
393-
}
391+
return String.format("%s %s %s", c.getName(), c.getOp(), toZQLConditionString(c.getValue(), true));
392+
} else {
393+
return String.format("%s %s %s", c.getName(), c.getOp(), toZQLConditionString(c.getValue(), false));
394+
}
395+
}
394396

395-
if (values.isEmpty()) {
396-
// use '' to represent an empty collection
397-
values.add("''");
397+
private static String toZQLConditionString(String rawText, final boolean supportSplitByComma) {
398+
if (rawText.isEmpty()) {
399+
return supportSplitByComma ? "('')" : "''";
400+
}
401+
402+
boolean specialCharFound = rawText.contains("'") || rawText.contains("\\");
403+
specialCharFound |= (supportSplitByComma && rawText.contains(","));
404+
if (!specialCharFound) {
405+
return supportSplitByComma ? "('" + rawText + "')" : '\'' + rawText + '\'';
406+
}
407+
408+
StringBuilder builder = new StringBuilder(rawText.length() << 1);
409+
IntConsumer consumer = supportSplitByComma ? ch -> {
410+
switch (ch) {
411+
case '\'': builder.append("\\'"); break;
412+
case '\\': builder.append("\\\\"); break;
413+
case ',': builder.append("','"); break;
414+
default: builder.append((char) ch); break;
415+
}
416+
} : ch -> {
417+
switch (ch) {
418+
case '\'': builder.append("\\'"); break;
419+
case '\\': builder.append("\\\\"); break;
420+
default: builder.append((char) ch); break;
398421
}
422+
};
399423

400-
return String.format("%s %s (%s)", c.getName(), c.getOp(), StringUtils.join(values, ","));
401-
} else {
402-
return String.format("%s %s '%s'", c.getName(), c.getOp(), c.getValue());
424+
builder.append('\'');
425+
rawText.chars().forEach(consumer);
426+
builder.append('\'');
427+
428+
if (supportSplitByComma) {
429+
builder.insert(0, '(');
430+
builder.append(')');
403431
}
432+
433+
return builder.toString();
404434
}
405435

406436
private Class getQueryTargetInventoryClass(APIQueryMessage msg, Class inventoryClass) {
@@ -431,9 +461,7 @@ public ZQLQueryReturn queryUseZQL(APIQueryMessage msg, Class inventoryClass) {
431461

432462
if (msg.getConditions() != null && !msg.getConditions().isEmpty()) {
433463
Set<String> conds = new HashSet<>();
434-
msg.getConditions().forEach(c -> {
435-
conds.add(toZQLConditionString(c));
436-
});
464+
msg.getConditions().forEach(c -> conds.add(toZQLConditionString(c)));
437465

438466
if (!conds.isEmpty()) {
439467
sb.add("where");
@@ -465,17 +493,24 @@ public ZQLQueryReturn queryUseZQL(APIQueryMessage msg, Class inventoryClass) {
465493
sb.add(String.format("offset %s", msg.getStart()));
466494
}
467495

468-
ZQLContext.putAPISession(msg.getSession());
469496
String text = StringUtils.join(sb, " ");
470497
if (logger.isTraceEnabled()) {
471498
logger.trace(text);
472499
}
473500
ZQL zql = ZQL.fromString(text);
474-
ZQLQueryReturn result = zql.getSingleResult();
501+
ZQLQueryReturn result;
502+
503+
try {
504+
ZQLContext.putAPISession(msg.getSession());
505+
result = zql.getSingleResult();
506+
} finally {
507+
ZQLContext.cleanAPISession();
508+
}
509+
475510
if (result.inventories != null) {
476511
dropAPINoSee(result.inventories, targetInventoryClass);
477512
}
478-
ZQLContext.cleanAPISession();
513+
479514
return result;
480515
}
481516

0 commit comments

Comments
 (0)