diff --git a/src/builtin.c b/src/builtin.c index cf4792c446..741e2fb585 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -295,7 +295,13 @@ static jv f_endswith(jq_state *jq, jv a, jv b) { } static jv f_ltrimstr(jq_state *jq, jv input, jv left) { - if (jv_get_kind(f_startswith(jq, jv_copy(input), jv_copy(left))) != JV_KIND_TRUE) { + jv startswith = f_startswith(jq, jv_copy(input), jv_copy(left)); + if (!jv_is_valid(startswith)) { + jv_free(input); + jv_free(left); + return startswith; + } + if (jv_get_kind(startswith) != JV_KIND_TRUE) { jv_free(left); return input; } @@ -311,14 +317,21 @@ static jv f_ltrimstr(jq_state *jq, jv input, jv left) { } static jv f_rtrimstr(jq_state *jq, jv input, jv right) { - if (jv_get_kind(f_endswith(jq, jv_copy(input), jv_copy(right))) == JV_KIND_TRUE) { - jv res = jv_string_sized(jv_string_value(input), - jv_string_length_bytes(jv_copy(input)) - jv_string_length_bytes(right)); + jv endswith = f_endswith(jq, jv_copy(input), jv_copy(right)); + if (!jv_is_valid(endswith)) { jv_free(input); - return res; + jv_free(right); + return endswith; } - jv_free(right); - return input; + if (jv_get_kind(endswith) != JV_KIND_TRUE) { + jv_free(right); + return input; + } + int suffixlen = jv_string_length_bytes(right); + jv res = jv_string_sized(jv_string_value(input), + jv_string_length_bytes(jv_copy(input)) - suffixlen); + jv_free(input); + return res; } jv binop_minus(jv a, jv b) { diff --git a/tests/jq.test b/tests/jq.test index c5c8cf0630..93d70a5014 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -2091,3 +2091,18 @@ try ("foobar" | .[1.5]) catch . null "Cannot index string with number" +# ltrimstr/1 and rtrimstr/1 don't leak, and return an error for +# non-string arguments. #2969 +.[] as [$x, $y] | try ["ok", ($x | ltrimstr($y))] catch ["ko", .] +[["hi",1],[1,"hi"],["hi","hi"],[1,1]] +["ko","startswith() requires string inputs"] +["ko","startswith() requires string inputs"] +["ok",""] +["ko","startswith() requires string inputs"] + +.[] as [$x, $y] | try ["ok", ($x | rtrimstr($y))] catch ["ko", .] +[["hi",1],[1,"hi"],["hi","hi"],[1,1]] +["ko","endswith() requires string inputs"] +["ko","endswith() requires string inputs"] +["ok",""] +["ko","endswith() requires string inputs"]