MCPcopy Create free account
hub / github.com/LibPDF-js/core / parseStream

Method parseStream

src/parser/xref-parser.ts:195–340  ·  view source on GitHub ↗

* Parse xref stream format (PDF 1.5+). * Scanner must be positioned at stream object start ("N M obj"). * * XRef streams encode cross-reference data as binary in a stream object. * The stream dictionary contains: * - /Type /XRef * - /Size - total number of objects * - /W [w1 w2

()

Source from the content-addressed store, hash-verified

193 * - /Index [first count ...] - object number ranges (optional, defaults to [0 Size])
194 */
195 parseStream(): XRefData {
196 // Parse the indirect object containing the xref stream
197 const parser = new IndirectObjectParser(this.scanner);
198 const indirectObj = parser.parseObject();
199
200 if (!(indirectObj.value instanceof PdfStream)) {
201 throw new XRefParseError("Expected XRef stream object");
202 }
203
204 const stream = indirectObj.value;
205
206 // Validate /Type is /XRef (optional per spec, but good to check)
207 const type = stream.getName("Type");
208 if (type !== undefined && type.value !== "XRef") {
209 throw new XRefParseError(`Expected /Type /XRef, got /Type /${type.value}`);
210 }
211
212 // Get required /W array (field widths)
213 const wArray = stream.getArray("W");
214 if (wArray === undefined || wArray.length < 3) {
215 throw new XRefParseError("XRef stream missing or invalid /W array");
216 }
217
218 const w0 = wArray.at(0);
219 const w1Val = wArray.at(1);
220 const w2Val = wArray.at(2);
221
222 const w1 = w0 instanceof PdfNumber ? w0.value : 0; // Type field width
223 const w2 = w1Val instanceof PdfNumber ? w1Val.value : 0; // Offset field width
224 const w3 = w2Val instanceof PdfNumber ? w2Val.value : 0; // Generation field width
225
226 // Validate field widths to prevent integer overflow during parsing.
227 // JavaScript safely handles integers up to 2^53-1, but bitwise operations
228 // are limited to 32 bits. Fields wider than 6 bytes (48 bits) could cause
229 // issues with shift operations. Most PDFs use 1-4 byte widths.
230 const MAX_FIELD_WIDTH = 6;
231
232 if (w1 < 0 || w1 > MAX_FIELD_WIDTH) {
233 throw new XRefParseError(`Invalid XRef stream field width w1=${w1} (max ${MAX_FIELD_WIDTH})`);
234 }
235
236 if (w2 < 0 || w2 > MAX_FIELD_WIDTH) {
237 throw new XRefParseError(`Invalid XRef stream field width w2=${w2} (max ${MAX_FIELD_WIDTH})`);
238 }
239
240 if (w3 < 0 || w3 > MAX_FIELD_WIDTH) {
241 throw new XRefParseError(`Invalid XRef stream field width w3=${w3} (max ${MAX_FIELD_WIDTH})`);
242 }
243
244 const entrySize = w1 + w2 + w3;
245
246 // Get /Size (total object count)
247 const size = stream.getNumber("Size")?.value;
248 if (size === undefined) {
249 throw new XRefParseError("XRef stream missing /Size");
250 }
251
252 // Get /Index array or default to [0 Size]

Callers 2

parseAtMethod · 0.95

Calls 9

parseObjectMethod · 0.95
getArrayMethod · 0.80
atMethod · 0.80
pushMethod · 0.80
getDecodedDataMethod · 0.80
getNameMethod · 0.65
getNumberMethod · 0.45
hasMethod · 0.45
setMethod · 0.45

Tested by

no test coverage detected