Check the canvas size before narrowing it to an int
A canvas side was cast to int with no range check, so a number that did not fit came back as one that did: `-s 4294968296x600` rendered a perfectly plausible 1000x600, and a hand-edited project file could ask for a width the reader turned into something else (or, for a double out of range, into undefined behaviour). Both front-ends now check the side before the cast, against one shared bound in chain.hpp — the 1..20000 the GUI spin buttons already offered, so the help text, the CLI error, the project reader and the interface all move together. The tests gain a `canvas size` section covering the round trip at both ends of the range and the refusals on either side of it, through the project reader and through `-s`; the test binary picks up the CLI parser to do it, which stays GUI-free. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+9
-3
@@ -24,7 +24,10 @@ bool parseSize(const std::string& text, int& width, int& height) {
|
||||
long w = 0;
|
||||
long h = 0;
|
||||
if (!parseLong(text.substr(0, sep), w) || !parseLong(text.substr(sep + 1), h)) return false;
|
||||
if (w <= 0 || h <= 0) return false;
|
||||
// Checked as longs, before the narrowing: 4294968296 cast straight to int
|
||||
// is 1000, which would render a plausible canvas nobody asked for.
|
||||
if (w < kMinCanvasSide || w > kMaxCanvasSide) return false;
|
||||
if (h < kMinCanvasSide || h > kMaxCanvasSide) return false;
|
||||
width = static_cast<int>(w);
|
||||
height = static_cast<int>(h);
|
||||
return true;
|
||||
@@ -66,7 +69,9 @@ Options parseOptions(int argc, char** argv) {
|
||||
} else if (arg == "-s" || arg == "--size") {
|
||||
const std::string value = requireValue(argc, argv, i, arg);
|
||||
if (!parseSize(value, options.width, options.height)) {
|
||||
throw EffectError("invalid size '" + value + "', expected e.g. 1920x1080");
|
||||
throw EffectError("invalid size '" + value + "', expected e.g. 1920x1080 with "
|
||||
"each side between " + std::to_string(kMinCanvasSide) + " and " +
|
||||
std::to_string(kMaxCanvasSide));
|
||||
}
|
||||
} else if (arg == "--seed") {
|
||||
const std::string value = requireValue(argc, argv, i, arg);
|
||||
@@ -131,7 +136,8 @@ std::string usage(const char* programName) {
|
||||
<< "Options:\n"
|
||||
<< " -e, --effect NAME effect to apply, repeat to cascade (default: " << defaultEffectName() << ")\n"
|
||||
<< " -o, --output FILE render headlessly to this file and exit\n"
|
||||
<< " -s, --size WxH canvas size (default: 1920x1080)\n"
|
||||
<< " -s, --size WxH canvas size, each side " << kMinCanvasSide << "-"
|
||||
<< kMaxCanvasSide << " (default: 1920x1080)\n"
|
||||
<< " --seed N random seed (default: random)\n"
|
||||
<< " --list-effects list available effects and exit\n"
|
||||
<< " -h, --help show this help and exit\n";
|
||||
|
||||
Reference in New Issue
Block a user