mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-30 08:50:48 +01:00
s3vectors: reject empty boolean-operator lists and sub-objects in filters (#12220)
* s3vectors: reject empty boolean-operator lists and sub-objects in filters An empty $and/$or list or a nested empty object rendered '()'' — invalid SQL surfaced as an engine error instead of a clean ValidationException. * s3vectors: reject field operator objects with no operators
This commit is contained in:
1 parent
3f954e34dc
commit
9d5929a73f
2 files changed
+22
-6
No files matched your search
@@ -1532,6 +1532,9 @@ func filterExpr(filter map[string]interface{}) (string, error) {
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%s expects a list", key)
|
||||
}
|
||||
if len(sub) == 0 {
|
||||
return "", fmt.Errorf("%s expects a non-empty list", key)
|
||||
}
|
||||
exprs := make([]string, 0, len(sub))
|
||||
for _, item := range sub {
|
||||
m, ok := item.(map[string]interface{})
|
||||
@@ -1542,6 +1545,9 @@ func filterExpr(filter map[string]interface{}) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if e == "" {
|
||||
return "", fmt.Errorf("%s expects non-empty objects", key)
|
||||
}
|
||||
exprs = append(exprs, e)
|
||||
}
|
||||
joiner := " AND "
|
||||
@@ -1684,6 +1690,9 @@ func fieldClause(field string, cond interface{}) (string, error) {
|
||||
return "", fmt.Errorf("unsupported operator %s", op)
|
||||
}
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
return "", fmt.Errorf("%s expects at least one operator", field)
|
||||
}
|
||||
return strings.Join(parts, " AND "), nil
|
||||
default:
|
||||
lit, err := sqlLiteral(cond)
|
||||
|
||||
@@ -336,12 +336,19 @@ func TestTranslateFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
for name, filter := range map[string]map[string]interface{}{
|
||||
"unknown operator": {"k": map[string]interface{}{"$bogus": "v"}},
|
||||
"exists non-bool": {"k": map[string]interface{}{"$exists": "yes"}},
|
||||
"range non-number": {"k": map[string]interface{}{"$gt": "v"}},
|
||||
"in non-list": {"k": map[string]interface{}{"$in": "v"}},
|
||||
"top-level bad op": {"$bogus": []interface{}{}},
|
||||
"nested bad member": {"$and": []interface{}{"x"}},
|
||||
"unknown operator": {"k": map[string]interface{}{"$bogus": "v"}},
|
||||
"exists non-bool": {"k": map[string]interface{}{"$exists": "yes"}},
|
||||
"range non-number": {"k": map[string]interface{}{"$gt": "v"}},
|
||||
"in non-list": {"k": map[string]interface{}{"$in": "v"}},
|
||||
"top-level bad op": {"$bogus": []interface{}{}},
|
||||
"nested bad member": {"$and": []interface{}{"x"}},
|
||||
"empty and list": {"$and": []interface{}{}},
|
||||
"empty or list": {"$or": []interface{}{}},
|
||||
"empty sub-object": {"$and": []interface{}{map[string]interface{}{}}},
|
||||
"empty operators": {"k": map[string]interface{}{}},
|
||||
"empty among fields": {"k": map[string]interface{}{}, "j": "1"},
|
||||
"empty under and": {"$and": []interface{}{map[string]interface{}{
|
||||
"k": map[string]interface{}{}, "j": map[string]interface{}{}}}},
|
||||
} {
|
||||
if _, err := translateFilter(filter); err == nil {
|
||||
t.Fatalf("%s should fail", name)
|
||||
|
||||
Reference in new issue
Block a user