fix(raw): fix infinite loop in JPEG binary scanner and ensure sub-100ms preview extraction
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user