fix(raw): fix infinite loop in JPEG binary scanner and ensure sub-100ms preview extraction

This commit is contained in:
2026-10-06 15:34:20 +07:00
parent c4d95e5722
commit 16c098cd6a
+41 -36
View File
@@ -260,60 +260,65 @@ export function extractEmbeddedJpeg(buf: Uint8Array): Uint8Array | null {
const len = buf.length;
let largest: Uint8Array | null = null;
let maxLen = 0;
for (let i = 0; i < len - 4; i++) {
if (buf[i] === 0xff && buf[i + 1] === 0xd8 && buf[i + 2] === 0xff) {
const start = i;
let pos = i + 2;
let eoiPos = -1;
let valid = true;
while (pos < len - 1) {
let validJpeg = true;
while (pos < len - 4) {
if (buf[pos] !== 0xff) {
pos++;
continue;
validJpeg = false;
break;
}
const marker = buf[pos + 1];
if (marker === 0x00 || (marker >= 0xd0 && marker <= 0xd7)) {
pos += 2;
continue;
}
if (marker === 0xd9) {
const m = buf[pos + 1];
if (m === 0xd9) {
eoiPos = pos + 2;
break;
}
if (marker === 0xd8) {
if (m === 0xda) {
const sosHeaderLen = (buf[pos + 2] << 8) | buf[pos + 3];
if (sosHeaderLen < 2 || pos + 2 + sosHeaderLen > len) {
validJpeg = false;
break;
}
let scanPos = pos + 2 + sosHeaderLen;
const searchEnd = Math.min(len - 1, scanPos + 20 * 1024 * 1024);
while (scanPos < searchEnd) {
if (buf[scanPos] === 0xff) {
const marker = buf[scanPos + 1];
if (marker === 0xd9) {
eoiPos = scanPos + 2;
break;
}
if (marker === 0x00 || (marker >= 0xd0 && marker <= 0xd7)) {
scanPos += 2;
continue;
}
}
scanPos++;
}
break;
}
if (m === 0x00 || (m >= 0xd0 && m <= 0xd7)) {
pos += 2;
continue;
}
if (pos + 3 >= len) break;
const segLen = (buf[pos + 2] << 8) | buf[pos + 3];
if (segLen < 2) {
valid = false;
if (segLen < 2 || pos + 2 + segLen > len) {
validJpeg = false;
break;
}
if (marker === 0xda) {
pos += 2 + segLen;
while (pos < len - 1) {
if (buf[pos] === 0xff) {
const m = buf[pos + 1];
if (m === 0xd9) {
eoiPos = pos + 2;
break;
}
if (m !== 0x00 && !(m >= 0xd0 && m <= 0xd7)) {
break;
}
}
pos++;
}
if (eoiPos !== -1) break;
} else {
pos += 2 + segLen;
}
pos += 2 + segLen;
}
if (valid && eoiPos > i) {
const segSize = eoiPos - i;
if (eoiPos > start && validJpeg) {
const segSize = eoiPos - start;
if (segSize > 10000 && segSize > maxLen) {
maxLen = segSize;
largest = buf.subarray(i, eoiPos);
largest = buf.subarray(start, eoiPos);
}
i = eoiPos - 1;
}