QR: skip QImage padding when filling quirc buffer
What changed, and why it matters
This commit fixes a bug in how the Monero GUI's QR code scanner copied image data into the quirc QR decoder library. Previously, the code copied the entire QImage buffer byte-for-byte, including padding bytes that Qt adds at the end of each image row. The new code copies each row individually, skipping the padding. This could have caused quirc to misread QR codes or, in a worst-case scenario, feed malformed data to the decoder. There is no direct evidence in the commit of an exploitable security vulnerability such as memory corruption.
Treat as a correctness/reliability fix. Review the updated quirc submodule changelog for any related security fixes. If the application processes untrusted QR images, consider fuzzing the decoder input path and verifying quirc's robustness against malformed buffers.
Security signals we found
Buffer handling change in QR decoder input path
Potential malformed input to third-party C library (quirc)
No explicit security claim by vendor in commit message
Evidence from the diff
The patch changes QrDecoder::decodeGrayscale8() in src/QR-Code-scanner/Decoder.cpp. It replaces a std::copy of image.constBits() over sizeInBytes()/byteCount() with a per-row std::memcpy from image.constScanLine(y) of exactly width bytes. QImage rows can be padded to align to 4-byte boundaries, so the old code included stride padding in the buffer passed to quirc. The new code strips that padding. The quirc submodule is also updated. The commit message frames this as a correctness fix, not a security fix, and no CVE or security advisory is referenced.
Changed components
src/QR-Code-scanner/Decoder.cppexternal/quircInspect captured patch +10 / −6
diff --git a/src/QR-Code-scanner/Decoder.cpp b/src/QR-Code-scanner/Decoder.cpp
index 25ef0f0..5710000 100644
--- a/src/QR-Code-scanner/Decoder.cpp
+++ b/src/QR-Code-scanner/Decoder.cpp
@@ -28,6 +28,7 @@
#include "Decoder.h"
+#include <cstring>
#include <limits>
#include "quirc.h"
@@ -67,11 +68,14 @@ std::vector<std::string> QrDecoder::decodeGrayscale8(const QImage &image)
{
throw std::runtime_error("QUIRC: failed to get image buffer");
}
-#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
- std::copy(image.constBits(), image.constBits() + image.sizeInBytes(), rawImage);
-#else
- std::copy(image.constBits(), image.constBits() + image.byteCount(), rawImage);
-#endif
+
+ const int width = image.width();
+ const int height = image.height();
+ for (int y = 0; y < height; ++y)
+ {
+ std::memcpy(rawImage + y * width, image.constScanLine(y), width);
+ }
+
quirc_end(m_qr);
const int count = quirc_count(m_qr);
Why this scored 47/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.