diff --git a/c/qrcodegen.c b/c/qrcodegen.c index 1c06546..8d53419 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -704,7 +704,9 @@ static long getPenaltyScore(const uint8_t qrcode[]) { int total = qrsize * qrsize; // Note that size is odd, so dark/total != 1/2 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% int k = (int)((labs(dark * 20L - total * 10L) + total - 1) / total) - 1; + assert(0 <= k && k <= 9); result += k * PENALTY_N4; + assert(0 <= result && result <= 2568888L); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 return result; } diff --git a/cpp/qrcodegen.cpp b/cpp/qrcodegen.cpp index 081b19c..b0f02af 100644 --- a/cpp/qrcodegen.cpp +++ b/cpp/qrcodegen.cpp @@ -663,7 +663,11 @@ long QrCode::getPenaltyScore() const { int total = size * size; // Note that size is odd, so dark/total != 1/2 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% int k = static_cast((std::abs(dark * 20L - total * 10L) + total - 1) / total) - 1; + if (!(0 <= k && k <= 9)) + throw std::logic_error("Assertion error"); result += k * PENALTY_N4; + if (!(0 <= result && result <= 2568888L)) // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 + throw std::logic_error("Assertion error"); return result; } diff --git a/java/src/main/java/io/nayuki/qrcodegen/QrCode.java b/java/src/main/java/io/nayuki/qrcodegen/QrCode.java index 47edbdc..46f5d75 100644 --- a/java/src/main/java/io/nayuki/qrcodegen/QrCode.java +++ b/java/src/main/java/io/nayuki/qrcodegen/QrCode.java @@ -594,7 +594,9 @@ public final class QrCode { int total = size * size; // Note that size is odd, so dark/total != 1/2 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% int k = (Math.abs(dark * 20 - total * 10) + total - 1) / total - 1; + assert 0 <= k && k <= 9; result += k * PENALTY_N4; + assert 0 <= result && result <= 2568888; // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 return result; } diff --git a/python/qrcodegen.py b/python/qrcodegen.py index 254238c..3917456 100644 --- a/python/qrcodegen.py +++ b/python/qrcodegen.py @@ -470,7 +470,9 @@ class QrCode: total: int = size**2 # Note that size is odd, so dark/total != 1/2 # Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% k: int = (abs(dark * 20 - total * 10) + total - 1) // total - 1 + assert 0 <= k <= 9 result += k * QrCode._PENALTY_N4 + assert 0 <= result <= 2568888 # Non-tight upper bound based on default values of PENALTY_N1, ..., N4 return result diff --git a/rust/src/lib.rs b/rust/src/lib.rs index feb1947..2f6c713 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -678,7 +678,9 @@ impl QrCode { let total: i32 = size * size; // Note that size is odd, so dark/total != 1/2 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% let k: i32 = ((dark * 20 - total * 10).abs() + total - 1) / total - 1; + assert!(0 <= k && k <= 9); result += k * PENALTY_N4; + assert!(0 <= result && result <= 2568888); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 result } diff --git a/typescript-javascript/qrcodegen.ts b/typescript-javascript/qrcodegen.ts index e0426fc..036fc9e 100644 --- a/typescript-javascript/qrcodegen.ts +++ b/typescript-javascript/qrcodegen.ts @@ -531,7 +531,11 @@ namespace qrcodegen { const total: int = this.size * this.size; // Note that size is odd, so dark/total != 1/2 // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)% const k: int = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1; + if (!(0 <= k && k <= 9)) + throw "Assertion error"; result += k * QrCode.PENALTY_N4; + if (!(0 <= result && result <= 2568888)) // Non-tight upper bound based on default values of PENALTY_N1, ..., N4 + throw "Assertion error"; return result; }