Skip to content

Commit 94be934

Browse files
amabluea-maurice
amablue
authored andcommitted
Fixed the way we parse integers when doing map->vector conversions.
Previously, strings with leading 0's would convert those strings to integers. This doesn't match the behavior of other platforms though, where leading zeroes cause a key to be treated as a string instead of an integer. E.G. the string "001" should not parse to the integer 1. PiperOrigin-RevId: 270724879
1 parent 56dc61d commit 94be934

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

database/src/desktop/util_desktop.cc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@ bool HasVector(const Variant& variant) {
437437
bool ParseInteger(const char* str, int32_t* output) {
438438
assert(output);
439439
assert(str);
440+
// Integers must not have leading zeroes.
441+
if (str[0] == '0' && str[1] != '\0') {
442+
return false;
443+
}
440444
// Check if the key is numeric
441445
bool is_int = false;
442446
char* end_ptr = nullptr;
@@ -449,32 +453,30 @@ bool ParseInteger(const char* str, int32_t* output) {
449453
}
450454

451455
// Convert one level of map to vector if applicable.
452-
// Convert map to vector if
453-
// 1. map is not empty
454-
// 2. All the key are numeric
455-
// 3. If less or equal to half of the keys in the array is missing
456+
// Convert map to vector if:
457+
// 1. map is not empty and
458+
// 2. All the key are numeric and
459+
// 3. If less or equal to half of the keys in the array is missing.
456460
// This function assume no priority information remains in the variant.
457461
void ConvertMapToVector(Variant* variant) {
458462
assert(variant);
459463

460464
if (variant->is_map() && !variant->map().empty()) {
461465
int64_t max_index = -1;
462-
bool all_numeric = true;
463466
for (auto& it_child : variant->map()) {
464467
// Check if the key is numeric
465468
int32_t parse_value = 0;
466469
bool is_number =
467470
ParseInteger(it_child.first.string_value(), &parse_value);
468471
if (!is_number || parse_value < 0) {
469-
all_numeric = false;
470472
// If any one of the key is not numeric, there is no need to verify
471473
// other keys
472-
break;
474+
return;
473475
}
474476
max_index = max_index < parse_value ? parse_value : max_index;
475477
}
476478

477-
if (all_numeric && max_index < (2 * variant->map().size())) {
479+
if (max_index < (2 * variant->map().size())) {
478480
Variant array_result(
479481
std::vector<Variant>(max_index + 1, Variant::Null()));
480482
for (int i = 0; i <= max_index; ++i) {

database/src/desktop/util_desktop.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,10 @@ size_t GetEffectiveChildren(const Variant& variant,
188188
// Check if the variant or any of its children is vector.
189189
bool HasVector(const Variant& variant);
190190

191-
// Parse a base-ten input string into 32-bit integer
191+
// Parse a base-ten input string into 32-bit integer. Strings are parsed as
192+
// integers if they do not have leading 0's - if they do they are simply treated
193+
// as strings. This is done to match the behavior of the other database
194+
// implementations.
192195
bool ParseInteger(const char* str, int32_t* output);
193196

194197
// Prune the priorities and convert map into vector if applicable, to the

0 commit comments

Comments
 (0)