Repository navigation
Conversation
The Turtle parser resolves each base declaration (`@base`, `BASE`) against the base before it, and each relative IRI and each prefix declaration's IRI against the base, walking the whole base each time, and once more for each dot segment in it. A chain of relative bases, a long base, a base with dot segments, or many prefix declarations under one, takes time far beyond linear in the text on the main thread. A declaration makes no triple, so none of the read limits counted it, and the parser went on to the end of the text past them: a release small enough to pass every limit could hold the tab for a long time, on adding it from a link, on each later read of it or its catalog for the deck list, and on a Studio import. A Turtle text read under limits is now written to the parser in parts, as a JSON-LD text already is, and the parser gets no more once the text is past its limits. Before each part, the declarations that start in it are checked. More than 16 bases, more than 4,096 prefixes, a base whose path has a `.`, `..` or empty segment or an escape, or a base that can grow past 512 characters (the longest of the address and the absolute bases, with the relative ones added on), refuses the text with the read-limit error, as one past the other limits is: a release with releaseTooLarge, a deck file with deckFileTooLarge. No release the app writes has such a base, and a document needs a few prefixes. The search reads the text as the parser does, past strings, IRIs and comments, so a comment cannot hide a declaration and one quoted in a card's text is not counted; it takes time linear in the text, and where it could read a directive other than the parser, it errs toward a refusal. Both Solid clients do so, in a read of a document, in getSolidDatasetLinear and in parseQuads, and the clients' contract holds both to it, with growth cases for the time to refuse. A text read with no limits, from the user's own pod, has its declarations as it makes them. The docs on release and deck file limits say so. Refs: GHSA-q3q9-h5mp-3956
ixuz
enabled auto-merge
November 1, 2026 02:50
ixuz
added this pull request to the merge queue
Nov 1, 2026
Any commits made after this event will not be merged.
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Nov 1, 2026
… test
CodeQL flagged replace("<", "<a") as incomplete escaping (alert #13).
It was no escaping, only a way to make the base IRI one character too
long; writing that IRI out says so plainly and clears the alert.
ixuz
enabled auto-merge
November 1, 2026 04:34
ixuz
added this pull request to the merge queue
Nov 1, 2026
Any commits made after this event will not be merged.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
The Turtle parser resolves each base declaration (
@base,BASE) against the base before it. It resolves each relative IRI and each prefix declaration against the current base too, and it walks the whole base each time. Some bases, and many prefixes under one base, make the parse take time far beyond linear in the text, on the main thread. A declaration makes no triple, so none of the read limits counted it, and the parser read on to the end of the text even after a limit was passed. So a release small enough to pass every limit could still freeze the tab. This happened when the release was added from a link, on each later read of it or of its catalog for the deck list, and on a Studio import.This pull request changes four things:
writeTurtleinreadLimits.ts)..,..or empty segment or an escape in its path, or if a base can grow past 512 characters. The refusal is the usual read-limit error:releaseTooLargefor a release,deckFileTooLargefor a deck file. No release the app writes has such a base, and a document needs only a few prefixes.getSolidDatasetLinearand inparseQuads. The clients' contract tests hold both clients to it, and growth tests check that the time to refuse a text grows linearly. A text read with no limits, from the user's own pod, is parsed as before.docs/deck-library.mdanddocs/data-model.mdgive the new release and deck-file limits.docs/testing.mdlists the new growth test.Refs: GHSA-q3q9-h5mp-3956
Checklist
Refs:, notCloses:. Leave this unchecked otherwise.npm run checkpasses (lint, Markdown and spelling included),npm run lint:reusetoo if a file was added, andnpm run crosschecktoo ifns/ordecks/changed. (lint:reuseandcrosscheckn/a: no file was added, andns/anddecks/are unchanged)docs/is listed in docs/docs.ttl.packages/ui/src/i18n/). (n/a: no message changed; the refusal uses the existingreleaseTooLargeanddeckFileTooLarge)ns/was agreed in an issue first; no publishedns/shapes/*/vN.ttlordecks/*/vN.ttlwas edited; generated files were regenerated, not edited. (n/a:ns/,decks/and the generated files are unchanged)!and aBREAKING CHANGE:footer).npm run check:breakingsees a line ofapi/that goes, but not a feature removed, nor a reader that reads less than before.npm run lint:reuse), or a new deck its line inREUSE.toml; third-party content is credited. (n/a: no file, deck or third-party content added)npm run dev) and tried the change, and considered the user journeys.type(scope): subject,!and aBREAKING CHANGE:footer if it breaks something), with an imperative subject and a body that explains why (CONTRIBUTING.md).