{"record":{"id":"c70dbc79a212ed6a","repo":"Tencent/APIJSON","slug":"suffix-key-column-value-functi","errorCode":null,"errorMessage":"字符串 {suffix} 不合法！预编译模式下 {key}:\"column?value;function(arg0,arg1,...)?value...\" 中 ?value 必须符合正则表达式 {PATTERN_RANGE} 且不包含连续减号 -- 或注释符 /* ！不允许多余的空格！","messagePattern":"字符串 (.+?) 不合法！预编译模式下 (.+?):\"column\\?value;function\\(arg0,arg1,\\.\\.\\.\\)\\?value\\.\\.\\.\" 中 \\?value 必须符合正则表达式 (.+?) 且不包含连续减号 -- 或注释符 /\\* ！不允许多余的空格！","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":2595,"sourceCode":"\t\t\t\t// 解析函数内的参数\n\t\t\t\tString ckeys[] = parseArgsSplitWithComma(s, false, containRaw, allowAlias);\n\n\t\t\t\tString suffix = expression.substring(end + 1); //:contactCount\n\t\t\t\tString alias = null;\n\t\t\t\tif (allowAlias) {\n\t\t\t\t\tint index = suffix.lastIndexOf(\":\");\n\t\t\t\t\talias = index < 0 ? \"\" : suffix.substring(index + 1); //contactCount\n\t\t\t\t\tsuffix = index < 0 ? suffix : suffix.substring(0, index);\n\t\t\t\t\tif (alias.isEmpty() == false && StringUtil.isName(alias) == false) {\n\t\t\t\t\t\tthrow new IllegalArgumentException(\"字符串 \" + alias + \" 不合法！预编译模式下 \"\n\t\t\t\t\t\t\t\t+ key + \":value 中 value里面用 ; 分割的每一项\"\n\t\t\t\t\t\t\t\t+ \" function(arg0,arg1,...):alias 中 alias 必须是1个单词！并且不要有多余的空格！\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (suffix.isEmpty() == false && (suffix.contains(\"--\") || suffix.contains(\"/*\")\n\t\t\t\t\t\t|| PATTERN_RANGE.matcher(suffix).matches() == false)) {\n\t\t\t\t\tthrow new UnsupportedOperationException(\"字符串 \" + suffix + \" 不合法！预编译模式下 \" + key\n\t\t\t\t\t\t\t+ \":\\\"column?value;function(arg0,arg1,...)?value...\\\"\"\n\t\t\t\t\t\t\t+ \" 中 ?value 必须符合正则表达式 \" + PATTERN_RANGE + \" 且不包含连续减号 -- 或注释符 /* ！不允许多余的空格！\");\n\t\t\t\t}\n\n\t\t\t\tString origin = fun + \"(\" + (distinct ? PREFIX_DISTINCT : \"\") + StringUtil.get(ckeys) + \")\" + suffix;\n\t\t\t\texpression = origin + (StringUtil.isEmpty(alias, true) ? \"\" : gainAs() + quote + alias + quote);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t//是窗口函数   fun(arg0,agr1) OVER (agr0 agr1 ...)\n\t\t\t\tint keyIndex = containOver ? overIndex : againstIndex;\n\t\t\t\tString s1 = expression.substring(0, keyIndex + 1); // OVER 前半部分\n\t\t\t\tString s2 = expression.substring(keyIndex + 1); // OVER 后半部分\n\n\t\t\t\tint index1 = s1.indexOf(\"(\"); //  函数 \"(\" 的起始位置\n\t\t\t\tint end = s2.lastIndexOf(\")\"); // 后半部分 “)” 的位置\n\n\t\t\t\tif (index1 >= end + s1.length()) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"字符 \" + expression + \" 不合法！\"","sourceCodeStart":2577,"sourceCodeEnd":2613,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2577-L2613","documentation":"For expressions with functions, the suffix after ')' (and before the ':' alias separator) must be empty or match PATTERN_RANGE (only digits and the operators % , ! = < > / . + - * ^) and must not contain '--' or '/*'. Anything else — letters, spaces, parentheses — throws this UnsupportedOperationException, because suffixes are restricted to numeric comparison tails like '>1' or '%5<=3'.","triggerScenarios":"\"@column\":\"sum(id)>10 \" (trailing space), \"@column\":\"count(id) and 1=1\" (letters), \"@column\":\"sum(id)--\" (comment marker), \"@column\":\"max(id)/*x*/\" — all fail the range pattern or comment check.","commonSituations":"Porting WHERE-style conditions into @column suffixes; SQL-injection probes containing -- or /*; accidentally leaving trailing whitespace or newlines in generated expressions; using BETWEEN/AND keywords in the suffix.","solutions":["Keep the suffix to comparison operators and digits only, e.g. \"sum(id)>1\", \"max(id)%5<=3\", or remove it.","Strip whitespace from the expression before sending.","Never include -- or /*; they are treated as comment injection.","Move complex conditions to the proper key (e.g. @having) or a @raw entry."],"exampleFix":"// before\n{\"User\":{\"@column\":\"sum(id) > 10 \"}}\n// after\n{\"User\":{\"@column\":\"sum(id)>10\"}}","handlingStrategy":"validation","validationCode":"const RANGE=/^[0-9%,!=<>/\\.\\+\\-\\*\\^]+$/;\nconst tail=expr.slice(expr.lastIndexOf(')')+1).split(':')[0];\nif(tail && (tail.includes('--')||tail.includes('/*')||!RANGE.test(tail)))throw new Error('bad suffix');","typeGuard":"null","tryCatchPattern":"catch UnsupportedOperationException; strip suffix or move condition to @having/@raw and retry","preventionTips":["Suffix = operators+digits only","No keywords or spaces after ')'","Treat -- and /* as forbidden input everywhere"],"tags":["apijson","sql","security","input-validation","regex"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}