Skip to content

Commit 74799d6

Browse files
sbarzowskisparkprime
authored andcommitted
Fix std.substr out of bounds inconsistency
Make both Jsonnet and C++-native implementation clip the substring which go beyond the end of string.
1 parent 50dd6b4 commit 74799d6

File tree

4 files changed

+17
-2
lines changed

4 files changed

+17
-2
lines changed

core/vm.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,10 @@ class Interpreter {
14351435
ss << "substr third parameter should be greater than zero, got " << len;
14361436
throw makeError(loc, ss.str());
14371437
}
1438+
if (from > str->value.size()) {
1439+
scratch = makeString(UString());
1440+
return nullptr;
1441+
}
14381442
if (size_t(len + from) > str->value.size()) {
14391443
len = str->value.size() - from;
14401444
}

doc/ref/stdlib.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ <h4 id="substr">std.substr(s, from, len)</h4>
438438
<div class="panel">
439439
<p>
440440
Returns a string that is the part of <code>s</code> that starts at offset <code>from</code>
441-
and is <code>len</code> codepoints long.
441+
and is <code>len</code> codepoints long. If the string <code>s</code> is shorter than
442+
<code>from+len</code>, the suffix starting at position <code>from</code> will be returned.
442443
</p>
443444
</div>
444445
<div style="clear: both"></div>

stdlib/std.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ limitations under the License.
4545
else if len < 0 then
4646
error 'substr third parameter should be greater than zero, got ' + len
4747
else
48-
std.join('', std.makeArray(len, function(i) str[i + from])),
48+
std.join('', std.makeArray(std.max(0, std.min(len, std.length(str) - from)), function(i) str[i + from])),
4949

5050
startsWith(a, b)::
5151
if std.length(a) < std.length(b) then

test_suite/stdlib.jsonnet

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,16 @@ std.assertEqual(std.toString([1, 2, 'foo']), '[1, 2, "foo"]') &&
157157

158158
std.assertEqual(std.substr('cookie', 1, 3), 'ook') &&
159159
std.assertEqual(std.substr('cookie', 1, 0), '') &&
160+
std.assertEqual(std.substr('cookie', 1, 15), 'ookie') &&
161+
std.assertEqual(std.substr('cookie', 0, 5), 'cooki') &&
162+
std.assertEqual(std.substr('cookie', 0, 6), 'cookie') &&
163+
std.assertEqual(std.substr('cookie', 0, 15), 'cookie') &&
164+
std.assertEqual(std.substr('cookie', 3, 1), 'k') &&
165+
std.assertEqual(std.substr('cookie', 20, 1), '') &&
166+
std.assertEqual(std.substr('cookie', 6, 1), '') &&
167+
168+
169+
std.assertEqual(std.substr('ąę', 1, 1), 'ę') &&
160170

161171
std.assertEqual(std.startsWith('food', 'foo'), true) &&
162172
std.assertEqual(std.startsWith('food', 'food'), true) &&

0 commit comments

Comments
 (0)