Conversation
a % -1 is 0 for every a, and inja already renders 0 for it. The one exception is INT64_MIN, where the raw integer % overflows and raises SIGFPE, killing the host process with no exception to catch. divisibleBy has the same hole: its divisor != 0 short circuit lets -1 through to the same raw %. Op::Division is safe because it converts to number_float_t first, so these are the only two sites. No input that works today changes: the guard returns the 0 and the true that the same expression already returns for every other dividend.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
{{ a % b }}renders0for everyawhenbis-1, excepta = -9223372036854775808, where the raw integer%overflows and raises SIGFPE. The host process dies; there is no exception to catch, unlike every other bad-input path here.divisibleByhas the same hole: itsdivisor != 0short circuit lets-1through to the same raw%(renderer.hpp:364).Op::Division(:305-311) is safe because it converts tonumber_float_tfirst, so these two are the only sites.Nothing that works today changes. The guard returns the
0and thetruethat the same expression already returns for every other dividend, so there is no new exception and no new message. This follows #347, which covered the divisor0case;-1is the other way that%traps.Verification
g++ -std=c++17 -O1 -Wall -Wextra -Werror -D__TEST_DIR__=test -Iinclude -Ithird_party/include test/test.cpp.md5sum include/inja/renderer.hppon every row;test/test-functions.cppis constant across rows.renderer.hpp01f8a630HEADc7d6e23f40 passed, thenCRASHED: SIGFPEOp::Moduloonlyfed8786e40 passed, then SIGFPEOp::DivisibleByonly4762636071 passed, then SIGFPEdivisor <= -180167192{{ 7 % -2 }}gives0, want19260e293{{ int_min % 3 }}gives0, want-2The two revert rows crash at different assertion counts, so each site is independently required. The two over-correction rows pin both axes: widening the divisor test breaks an existing row at
test-functions.cpp:43, and guarding the dividend breaks the newint_min % 3row.Also run: the
single_inja_testconfiguration against the regeneratedsingle_include/inja/inja.hpp,269 | 269 passed; and-fsanitize=address,undefined -fno-sanitize-recover=all, clean.single_includewas regenerated withscripts/update_single_include.shand differs from HEAD by exactly the fix lines.Test rows go in
test/test-functions.cpp, in themathanddivisibleBysubcases next to the ones #347 added.Not run here: cmake, and the clang / clang-tidy / Windows / macOS matrix rows.
Disclosure: this change was written with AI assistance (Claude). The measurements above were reproduced and checked by me before opening this PR.