{"record":{"id":"860cefadf75d7cfa","repo":"spring-projects/spring-ai","slug":"unreasonable-linelength-of-d-provided","errorCode":null,"errorMessage":"Unreasonable lineLength of %d provided","messagePattern":"Unreasonable lineLength of (.+?) provided","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"document-readers/spring-ai-pdf-document-reader/src/main/java/org/springframework/ai/reader/pdf/layout/TextLine.java","lineNumber":45,"sourceCode":"\n\tprivate static final char SPACE_CHARACTER = ' ';\n\n\tprivate final int lineLength;\n\n\tprivate final char[] line;\n\n\tprivate int lastIndex;\n\n\tTextLine(int lineLength) {\n\t\tif (lineLength < 0) {\n\t\t\tthrow new IllegalArgumentException(\"Line length cannot be negative\");\n\t\t}\n\t\telse if (lineLength > 14_400) {\n\t\t\t// Cap to a reasonable limit to prevent attack via excessive char allocation\n\t\t\t// below.\n\t\t\t// 14_400 pdf units is the recommendation for the max dimension of a page by\n\t\t\t// ISO 32000\n\t\t\tthrow new IllegalArgumentException(\"Unreasonable lineLength of %d provided\".formatted(lineLength));\n\t\t}\n\t\tthis.lineLength = lineLength / ForkPDFLayoutTextStripper.OUTPUT_SPACE_CHARACTER_WIDTH_IN_PT;\n\t\tthis.line = new char[this.lineLength];\n\t\tArrays.fill(this.line, SPACE_CHARACTER);\n\t}\n\n\tpublic void writeCharacterAtIndex(final Character character) {\n\t\tcharacter.setIndex(this.computeIndexForCharacter(character));\n\t\tint index = character.getIndex();\n\t\tchar characterValue = character.getCharacterValue();\n\t\tif (this.indexIsInBounds(index) && this.line[index] == SPACE_CHARACTER) {\n\t\t\tthis.line[index] = characterValue;\n\t\t}\n\t}\n\n\tpublic int getLineLength() {\n\t\treturn this.lineLength;\n\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/document-readers/spring-ai-pdf-document-reader/src/main/java/org/springframework/ai/reader/pdf/layout/TextLine.java#L27-L63","documentation":"TextLine's constructor caps line length at 14,400 PDF units — the ISO 32000 recommendation for maximum page dimension — to prevent memory-exhaustion attacks via excessive char allocation. A larger computed lineLength throws IllegalArgumentException.","triggerScenarios":"Layout-aware PDF extraction where computed line width from text positions exceeds 14,400 units — e.g. text drawn at enormous X scale, huge font sizes, or content streams placing text far beyond any valid page — reaching the TextLine constructor.","commonSituations":"Adversarial PDFs crafted to trigger huge allocations (resource-exhaustion); corrupted documents with extreme text matrices; PDFs with oversized user-defined page dimensions from non-compliant generators.","solutions":["Pre-validate page dimensions/text scaling with PDFBox before extraction and reject non-compliant pages (max dimension 14,400 units per ISO 32000).","Normalize the PDF with qpdf/ghostscript to clamp extreme coordinates and scales.","Catch IllegalArgumentException and skip/quarantine the document in ingestion pipelines.","Disable layout-aware extraction so TextLine is never constructed for pathological input.","If legitimate oversized pages must be processed, adjust the 14,400 cap in a forked TextLine."],"exampleFix":"// before\nList<Document> docs = new PagePdfDocumentReader(resource,\n    PagePdfDocumentReader.config().withLayoutEnabled()).get();\n\n// after\ntry (PDDocument pd = Loader.loadPDF(resource.getFile())) {\n    float maxDim = 0;\n    for (PDPage p : pd.getPages()) {\n        maxDim = Math.max(maxDim, Math.max(p.getMediaBox().getWidth(), p.getMediaBox().getHeight()));\n    }\n    if (maxDim > 14_400) throw new IllegalArgumentException(\"page exceeds ISO 32000 max dimension\");\n}\nList<Document> docs = new PagePdfDocumentReader(resource,\n    PagePdfDocumentReader.config().withLayoutEnabled()).get();","handlingStrategy":"validation","validationCode":"try (PDDocument doc = Loader.loadPDF(file)) {\n    for (PDPage page : doc.getPages()) {\n        PDRectangle mb = page.getMediaBox();\n        if (mb.getWidth() > 14_400 || mb.getHeight() > 14_400)\n            throw new IllegalArgumentException(\n                \"page exceeds ISO 32000 max dimension (14400): \" + mb);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    List<Document> docs = new PagePdfDocumentReader(resource,\n        PagePdfDocumentReader.config().withLayoutEnabled()).get();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unreasonable lineLength\")) {\n        log.warn(\"Rejecting PDF with oversized line geometry: {}\", resource);\n        docs = List.of();\n    } else throw e;\n}","preventionTips":["Enforce the ISO 32000 14,400-unit max page dimension at document acceptance time","Clamp extreme font sizes and horizontal scales when generating PDFs yourself","Pre-normalize third-party PDFs (qpdf/ghostscript) before layout-aware extraction","For legitimate oversized pages, fork TextLine and raise the cap deliberately","Catch IllegalArgumentException per document in pipelines so one bad file doesn't abort ingestion"],"tags":["pdf","invalid-argument","memory-protection","text-extraction"],"backgroundTag":"invalid-argument-value","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}