Skip to content

validate structuredQuery shape before json access in bundle decoder#16251

Open
alhudz wants to merge 1 commit into
firebase:mainfrom
alhudz:bundle-query-json-shape
Open

validate structuredQuery shape before json access in bundle decoder#16251
alhudz wants to merge 1 commit into
firebase:mainfrom
alhudz:bundle-query-json-shape

Conversation

@alhudz

@alhudz alhudz commented Jun 10, 2026

Copy link
Copy Markdown

Firestore bundle query decoding (reached via loadBundle, where the bundle is commonly fetched from a CDN) reads parsed JSON without checking its shape, so a malformed bundle throws an uncaught nlohmann exception instead of failing the reader.

Repro: load a named query whose structuredQuery.from is a non-array, e.g. "from":"colls", or whose limit is an object with no value, e.g. "limit":{}.
Expected: the reader reports a decode failure.
Actual: DecodeCollectionSource calls get_ref<const std::vector<json>&>() with no is_array() guard and throws type_error.303; DecodeLimit calls limit_object.at("value") with no presence guard and throws out_of_range.403. Neither is caught on the decode path, so the process terminates.
Fix: guard both reads the way every sibling accessor in this file and in json_reader.cc already does, so malformed input fails the reader instead of throwing.

Added two regressions in bundle_serializer_test.cc.

@gemini-code-assist

Copy link
Copy Markdown
Contributor
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

@paulb777

Copy link
Copy Markdown
Member

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds validation checks to bundle_serializer.cc to ensure that the from clause is an array and that the limit object contains a valid integer value, along with corresponding unit tests. The reviewer suggested optimizing the limit object lookup by using find instead of contains and at to avoid redundant lookups.

Comment on lines +281 to 284
} else if (limit_object.is_object() && limit_object.contains("value") &&
limit_object.at("value").is_number_integer()) {
return limit_object.at("value").get<int32_t>();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

Using contains followed by multiple at calls results in redundant lookups in the JSON object. We can optimize this by using find to perform a single lookup.

Suggested change
} else if (limit_object.is_object() && limit_object.contains("value") &&
limit_object.at("value").is_number_integer()) {
return limit_object.at("value").get<int32_t>();
}
} else if (limit_object.is_object()) {
auto it = limit_object.find("value");
if (it != limit_object.end() && it->is_number_integer()) {
return it->get<int32_t>();
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants