diff --git a/QRCoder/QRCodeData.cs b/QRCoder/QRCodeData.cs index 37ee29a5..4355d9f3 100644 --- a/QRCoder/QRCodeData.cs +++ b/QRCoder/QRCodeData.cs @@ -55,7 +55,7 @@ public QRCodeData(string pathToRawData, Compression compressMode) : this(File.Re /// The compression mode used for the raw data. public QRCodeData(byte[] rawData, Compression compressMode) { - //Decompress + // Decompress if (compressMode == Compression.Deflate) { using var input = new MemoryStream(rawData); @@ -77,46 +77,53 @@ public QRCodeData(byte[] rawData, Compression compressMode) rawData = output.ToArray(); } - if (rawData.Length < 5) + const int HeaderLength = 5; // 4 bytes signature + 1 byte side length + + if (rawData.Length < HeaderLength) throw new InvalidDataException("Invalid raw data file. File too short."); - if (rawData[0] != 0x51 || rawData[1] != 0x52 || rawData[2] != 0x52) + + if (rawData[0] != 0x51 || rawData[1] != 0x52 || rawData[2] != 0x52 || rawData[3] != 0) throw new InvalidDataException("Invalid raw data file. Filetype doesn't match \"QRR\"."); // Set QR code version from side length (includes 8-module quiet zone) - var sideLen = (int)rawData[4]; + int sideLen = rawData[4]; if (sideLen < 29) // Micro QR: sideLen = 19 + 2*(m-1), m in [1..4] -> versions -1..-4 { - if (((sideLen - 19) & 1) != 0) + if (sideLen < 19 || sideLen > 25 || (sideLen & 1) == 0) throw new InvalidDataException("Invalid raw data file. Side length not valid for Micro QR."); - var m = ((sideLen - 19) / 2) + 1; - Version = -m; + + Version = -((sideLen - 17) >>> 1); } else // Standard QR: sideLen = 29 + 4*(v-1), v in [1..40] { - if (((sideLen - 29) % 4) != 0) + if (sideLen > 185 || (sideLen & 3) != 1) throw new InvalidDataException("Invalid raw data file. Side length not valid for QR."); - Version = ((sideLen - 29) / 4) + 1; + + Version = (sideLen - 25) >>> 2; } - //Unpack - var modules = new Queue(8 * (rawData.Length - 5)); - for (int j = 5; j < rawData.Length; j++) + int byteLength = (sideLen * sideLen + 7) >>> 3; + if (rawData.Length < 5 + byteLength) { - var b = rawData[j]; - for (int i = 7; i >= 0; i--) - { - modules.Enqueue((b & (1 << i)) != 0); - } + throw new InvalidDataException("Invalid raw data file. Not enough data."); } - //Build module matrix + // Build module matrix ModuleMatrix = new List(sideLen); + int bitIndex = HeaderLength * 8; // Skip header bytes + for (int y = 0; y < sideLen; y++) { - ModuleMatrix.Add(new BitArray(sideLen)); + var row = new BitArray(sideLen); + ModuleMatrix.Add(row); + for (int x = 0; x < sideLen; x++) { - ModuleMatrix[y][x] = modules.Dequeue(); + int byteIndex = bitIndex >>> 3; + int mask = 1 << (~bitIndex & 7); + row[x] = (rawData[byteIndex] & mask) != 0; + + bitIndex++; } } }