Skip to content

Commit 41c9505

Browse files
committed
Handle NUL on import
1 parent e26ca9b commit 41c9505

4 files changed

Lines changed: 49 additions & 4 deletions

File tree

ext/jsonnet/callbacks.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,7 @@ import_callback_entrypoint(void *ctx, const char *base, const char *rel, char **
130130
if (state) {
131131
VALUE msg = rescue_callback(state, "cannot import %s from %s", rel, base);
132132
#ifdef HAVE_JSONNET_IMPORT_CALLBACK_0_19
133-
*buf = rubyjsonnet_str_to_cstr(vm->vm, msg);
134-
*buflen = RSTRING_LEN(msg);
133+
*buf = rubyjsonnet_str_to_ptr(vm->vm, msg, buflen);
135134
return 1;
136135
#else
137136
*success = 0;
@@ -142,8 +141,7 @@ import_callback_entrypoint(void *ctx, const char *base, const char *rel, char **
142141
result = rb_Array(result);
143142
*found_here = rubyjsonnet_str_to_cstr(vm->vm, rb_ary_entry(result, 1));
144143
#ifdef HAVE_JSONNET_IMPORT_CALLBACK_0_19
145-
*buf = rubyjsonnet_str_to_cstr(vm->vm, rb_ary_entry(result, 0));
146-
*buflen = RSTRING_LEN(rb_ary_entry(result, 0));
144+
*buf = rubyjsonnet_str_to_ptr(vm->vm, rb_ary_entry(result, 0), buflen);
147145
return 0;
148146
#else
149147
*success = 1;

ext/jsonnet/helpers.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ rubyjsonnet_assert_asciicompat(VALUE str)
3434

3535
/**
3636
* Allocates a C string whose content is equal to \c str with jsonnet_realloc.
37+
*
38+
* Note that this function does not allow NUL characters in the string.
39+
* You should use rubyjsonnet_str_to_ptr() if you want to handle NUL characters.
40+
*
41+
* @param[in] vm a Jsonnet VM
42+
* @param[in] str a String-like object
43+
* @return the allocated C string
3744
*/
3845
char *
3946
rubyjsonnet_str_to_cstr(struct JsonnetVm *vm, VALUE str)
@@ -44,6 +51,25 @@ rubyjsonnet_str_to_cstr(struct JsonnetVm *vm, VALUE str)
4451
return buf;
4552
}
4653

54+
/**
55+
* Allocates a byte sequence whose content is equal to \c str with jsonnet_realloc.
56+
*
57+
* @param[in] vm a Jsonnet VM
58+
* @param[in] str a String-like object
59+
* @param[out] buflen the length of the allocated buffer
60+
* @return the allocated buffer
61+
*/
62+
char *
63+
rubyjsonnet_str_to_ptr(struct JsonnetVm *vm, VALUE str, size_t *buflen)
64+
{
65+
StringValue(str);
66+
size_t len = RSTRING_LEN(str);
67+
char *buf = jsonnet_realloc(vm, NULL, len);
68+
memcpy(buf, RSTRING_PTR(str), len);
69+
*buflen = len;
70+
return buf;
71+
}
72+
4773
/**
4874
* @return a human readable string which contains the class name of the
4975
* exception and its message. It might be nil on failure

ext/jsonnet/ruby_jsonnet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct JsonnetJsonValue *rubyjsonnet_obj_to_json(struct JsonnetVm *vm, VALUE obj
3333

3434
rb_encoding *rubyjsonnet_assert_asciicompat(VALUE str);
3535
char *rubyjsonnet_str_to_cstr(struct JsonnetVm *vm, VALUE str);
36+
char *rubyjsonnet_str_to_ptr(struct JsonnetVm *vm, VALUE str, size_t *buflen);
3637
VALUE rubyjsonnet_format_exception(VALUE exc);
3738
int rubyjsonnet_jump_tag(const char *exc_mesg);
3839

test/test_vm.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,26 @@ class TestVM < Test::Unit::TestCase
287287
assert_equal expected, JSON.parse(result)
288288
end
289289

290+
test "Jsonnet::VM#import_callback allows NUL char in Jsonnet v0.19 or later" do
291+
return unless Jsonnet.libversion >= "v0.19"
292+
293+
example_str = "\x0\x1".force_encoding(Encoding::BINARY)
294+
295+
vm = Jsonnet::VM.new
296+
vm.import_callback = ->(base, rel) {
297+
case [base, rel]
298+
when ['/path/to/base/', 'foo.bin']
299+
return "\x0\x1".force_encoding(Encoding::BINARY), '/path/to/base/foo.bin'
300+
else
301+
raise Errno::ENOENT, "#{rel} at #{base}"
302+
end
303+
}
304+
result = vm.evaluate(<<-EOS, filename: "/path/to/base/example.jsonnet")
305+
importbin "foo.bin"
306+
EOS
307+
assert_equal [0, 1], JSON.parse(result)
308+
end
309+
290310
test "Jsonnet::VM#evaluate returns an error if customized import callback raises an exception" do
291311
vm = Jsonnet::VM.new
292312
called = false

0 commit comments

Comments
 (0)