Compare commits

...

3 Commits

Author SHA1 Message Date
Daniel Lemire fb83b114ef 4.6.1 2026-04-03 15:26:12 -04:00
jmestwa-coder 542cd7af71 parser.load(string_view) does not respect view length when opening files (#2659) 2026-04-03 15:25:03 -04:00
Daniel Lemire 769364abb2 simplifying the logic 2026-03-30 20:01:35 -04:00
9 changed files with 33 additions and 32 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ endif()
project(
simdjson
# The version number is modified by tools/release.py
VERSION 4.6.0
VERSION 4.6.1
DESCRIPTION "Parsing gigabytes of JSON per second"
HOMEPAGE_URL "https://simdjson.org/"
LANGUAGES CXX C
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "4.6.0"
PROJECT_NUMBER = "4.6.1"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+2 -1
View File
@@ -36,10 +36,11 @@ inline bool parser::dump_raw_tape(std::ostream &os) const noexcept {
}
inline simdjson_result<size_t> parser::read_file(std::string_view path) noexcept {
const std::string path_copy(path);
// Open the file
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
std::FILE *fp = std::fopen(path.data(), "rb");
std::FILE *fp = std::fopen(path_copy.c_str(), "rb");
SIMDJSON_POP_DISABLE_WARNINGS
if (fp == nullptr) {
+3 -11
View File
@@ -355,8 +355,7 @@ inline padded_string padded_string_builder::convert() noexcept {
}
inline bool padded_string_builder::reserve(size_t additional) noexcept {
// Guard 1: size + additional must not wrap around.
if (simdjson_unlikely(additional > SIZE_MAX - size)) {
if (simdjson_unlikely(additional + size < size)) {
return false; // overflow: cannot satisfy request
}
size_t needed = size + additional;
@@ -367,16 +366,9 @@ inline bool padded_string_builder::reserve(size_t additional) noexcept {
// We are going to grow the capacity exponentially to avoid
// repeated allocations.
if (new_capacity < 4096) {
// Guard 2: doubling must not wrap around.
if (simdjson_unlikely(new_capacity > SIZE_MAX / 2)) {
return false; // overflow: fall back to exact allocation
}
new_capacity *= 2;
} else {
// Guard 3: 1.5x growth must not wrap around.
if (simdjson_unlikely(new_capacity > SIZE_MAX - new_capacity / 2)) {
return false; // overflow: fall back to exact allocation
}
// overflow guard: ensure new_capacity + new_capacity/2 does not overflow
} else if (new_capacity + new_capacity / 2 > new_capacity) {
new_capacity += new_capacity / 2; // grow by 1.5x
}
char *new_data = internal::allocate_padded_buffer(new_capacity);
+2 -2
View File
@@ -4,7 +4,7 @@
#define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION "4.6.0"
#define SIMDJSON_VERSION "4.6.1"
namespace simdjson {
enum {
@@ -19,7 +19,7 @@ enum {
/**
* The revision (major.minor.REVISION) of simdjson being used.
*/
SIMDJSON_VERSION_REVISION = 0
SIMDJSON_VERSION_REVISION = 1
};
} // namespace simdjson
+1 -1
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2026-03-30 10:16:31 -0400. version 4.6.0 Do not edit! */
/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */
/* including simdjson.cpp: */
/* begin file simdjson.cpp */
#define SIMDJSON_SRC_SIMDJSON_CPP
+8 -15
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2026-03-30 10:16:31 -0400. version 4.6.0 Do not edit! */
/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */
/* including simdjson.h: */
/* begin file simdjson.h */
#ifndef SIMDJSON_H
@@ -2538,7 +2538,7 @@ namespace std {
#define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION "4.6.0"
#define SIMDJSON_VERSION "4.6.1"
namespace simdjson {
enum {
@@ -2553,7 +2553,7 @@ enum {
/**
* The revision (major.minor.REVISION) of simdjson being used.
*/
SIMDJSON_VERSION_REVISION = 0
SIMDJSON_VERSION_REVISION = 1
};
} // namespace simdjson
@@ -5033,8 +5033,7 @@ inline padded_string padded_string_builder::convert() noexcept {
}
inline bool padded_string_builder::reserve(size_t additional) noexcept {
// Guard 1: size + additional must not wrap around.
if (simdjson_unlikely(additional > SIZE_MAX - size)) {
if (simdjson_unlikely(additional + size < size)) {
return false; // overflow: cannot satisfy request
}
size_t needed = size + additional;
@@ -5045,16 +5044,9 @@ inline bool padded_string_builder::reserve(size_t additional) noexcept {
// We are going to grow the capacity exponentially to avoid
// repeated allocations.
if (new_capacity < 4096) {
// Guard 2: doubling must not wrap around.
if (simdjson_unlikely(new_capacity > SIZE_MAX / 2)) {
return false; // overflow: fall back to exact allocation
}
new_capacity *= 2;
} else {
// Guard 3: 1.5x growth must not wrap around.
if (simdjson_unlikely(new_capacity > SIZE_MAX - new_capacity / 2)) {
return false; // overflow: fall back to exact allocation
}
// overflow guard: ensure new_capacity + new_capacity/2 does not overflow
} else if (new_capacity + new_capacity / 2 > new_capacity) {
new_capacity += new_capacity / 2; // grow by 1.5x
}
char *new_data = internal::allocate_padded_buffer(new_capacity);
@@ -9506,10 +9498,11 @@ inline bool parser::dump_raw_tape(std::ostream &os) const noexcept {
}
inline simdjson_result<size_t> parser::read_file(std::string_view path) noexcept {
const std::string path_copy(path);
// Open the file
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
std::FILE *fp = std::fopen(path.data(), "rb");
std::FILE *fp = std::fopen(path_copy.c_str(), "rb");
SIMDJSON_POP_DISABLE_WARNINGS
if (fp == nullptr) {
Binary file not shown.
+15
View File
@@ -114,6 +114,20 @@ namespace parser_load {
TEST_SUCCEED();
}
bool parser_load_string_view_subpath() {
TEST_START();
const std::string valid_path(TWITTER_JSON);
const std::string backing = valid_path + ".extra";
const std::string_view view(backing.data(), valid_path.size());
uint64_t count_from_string = 0;
uint64_t count_from_view = 0;
dom::parser parser;
ASSERT_SUCCESS(parser.load(valid_path)["search_metadata"]["count"].get(count_from_string));
ASSERT_SUCCESS(parser.load(view)["search_metadata"]["count"].get(count_from_view));
ASSERT_EQUAL(count_from_view, count_from_string);
TEST_SUCCEED();
}
bool parser_load_chain() {
TEST_START();
dom::parser parser;
@@ -136,6 +150,7 @@ namespace parser_load {
&& parser_load_nonexistent()
&& parser_load_many_nonexistent()
&& padded_string_load_nonexistent()
&& parser_load_string_view_subpath()
&& parser_load_chain()
&& parser_load_many_chain()
&& parser_parse_many_documents_error_in_the_middle()