mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
json: respect max_value_len when parsing std.json.Value (#17107)
This commit is contained in:
parent
a0968be83c
commit
7827265ea8
@ -81,7 +81,6 @@ pub const Value = union(enum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn jsonParse(allocator: Allocator, source: anytype, options: ParseOptions) ParseError(@TypeOf(source.*))!@This() {
|
pub fn jsonParse(allocator: Allocator, source: anytype, options: ParseOptions) ParseError(@TypeOf(source.*))!@This() {
|
||||||
_ = options;
|
|
||||||
// The grammar of the stack is:
|
// The grammar of the stack is:
|
||||||
// (.array | .object .string)*
|
// (.array | .object .string)*
|
||||||
var stack = Array.init(allocator);
|
var stack = Array.init(allocator);
|
||||||
@ -93,21 +92,21 @@ pub const Value = union(enum) {
|
|||||||
stack.items[stack.items.len - 1] == .array or
|
stack.items[stack.items.len - 1] == .array or
|
||||||
(stack.items[stack.items.len - 2] == .object and stack.items[stack.items.len - 1] == .string));
|
(stack.items[stack.items.len - 2] == .object and stack.items[stack.items.len - 1] == .string));
|
||||||
|
|
||||||
switch (try source.nextAlloc(allocator, .alloc_always)) {
|
switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
|
||||||
.allocated_string => |s| {
|
.allocated_string => |s| {
|
||||||
return try handleCompleteValue(&stack, allocator, source, Value{ .string = s }) orelse continue;
|
return try handleCompleteValue(&stack, allocator, source, Value{ .string = s }, options) orelse continue;
|
||||||
},
|
},
|
||||||
.allocated_number => |slice| {
|
.allocated_number => |slice| {
|
||||||
return try handleCompleteValue(&stack, allocator, source, Value.parseFromNumberSlice(slice)) orelse continue;
|
return try handleCompleteValue(&stack, allocator, source, Value.parseFromNumberSlice(slice), options) orelse continue;
|
||||||
},
|
},
|
||||||
|
|
||||||
.null => return try handleCompleteValue(&stack, allocator, source, .null) orelse continue,
|
.null => return try handleCompleteValue(&stack, allocator, source, .null, options) orelse continue,
|
||||||
.true => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = true }) orelse continue,
|
.true => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = true }, options) orelse continue,
|
||||||
.false => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = false }) orelse continue,
|
.false => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = false }, options) orelse continue,
|
||||||
|
|
||||||
.object_begin => {
|
.object_begin => {
|
||||||
switch (try source.nextAlloc(allocator, .alloc_always)) {
|
switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
|
||||||
.object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = ObjectMap.init(allocator) }) orelse continue,
|
.object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = ObjectMap.init(allocator) }, options) orelse continue,
|
||||||
.allocated_string => |key| {
|
.allocated_string => |key| {
|
||||||
try stack.appendSlice(&[_]Value{
|
try stack.appendSlice(&[_]Value{
|
||||||
Value{ .object = ObjectMap.init(allocator) },
|
Value{ .object = ObjectMap.init(allocator) },
|
||||||
@ -120,7 +119,7 @@ pub const Value = union(enum) {
|
|||||||
.array_begin => {
|
.array_begin => {
|
||||||
try stack.append(Value{ .array = Array.init(allocator) });
|
try stack.append(Value{ .array = Array.init(allocator) });
|
||||||
},
|
},
|
||||||
.array_end => return try handleCompleteValue(&stack, allocator, source, stack.pop()) orelse continue,
|
.array_end => return try handleCompleteValue(&stack, allocator, source, stack.pop(), options) orelse continue,
|
||||||
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
@ -134,7 +133,7 @@ pub const Value = union(enum) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, value_: Value) !?Value {
|
fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, value_: Value, options: ParseOptions) !?Value {
|
||||||
if (stack.items.len == 0) return value_;
|
if (stack.items.len == 0) return value_;
|
||||||
var value = value_;
|
var value = value_;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -152,7 +151,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val
|
|||||||
|
|
||||||
// This is an invalid state to leave the stack in,
|
// This is an invalid state to leave the stack in,
|
||||||
// so we have to process the next token before we return.
|
// so we have to process the next token before we return.
|
||||||
switch (try source.nextAlloc(allocator, .alloc_always)) {
|
switch (try source.nextAllocMax(allocator, .alloc_always, options.max_value_len.?)) {
|
||||||
.object_end => {
|
.object_end => {
|
||||||
// This object is complete.
|
// This object is complete.
|
||||||
value = stack.pop();
|
value = stack.pop();
|
||||||
|
|||||||
@ -302,6 +302,20 @@ test "long object value" {
|
|||||||
try testing.expectEqualStrings(value, parsed.value.object.get("key").?.string);
|
try testing.expectEqualStrings(value, parsed.value.object.get("key").?.string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "ParseOptions.max_value_len" {
|
||||||
|
var arena = ArenaAllocator.init(testing.allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
|
||||||
|
const str = "\"0800fc577294c34e0b28ad2839435945\"";
|
||||||
|
|
||||||
|
const value = try std.json.parseFromSliceLeaky(std.json.Value, arena.allocator(), str, .{ .max_value_len = 32 });
|
||||||
|
|
||||||
|
try testing.expect(value == .string);
|
||||||
|
try testing.expect(value.string.len == 32);
|
||||||
|
|
||||||
|
try testing.expectError(error.ValueTooLong, std.json.parseFromSliceLeaky(std.json.Value, arena.allocator(), str, .{ .max_value_len = 31 }));
|
||||||
|
}
|
||||||
|
|
||||||
test "many object keys" {
|
test "many object keys" {
|
||||||
const doc =
|
const doc =
|
||||||
\\{
|
\\{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user