Repository navigation
Bound memory and stack use when decoding and parsing #2813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
alexcrichton
merged 2 commits into
bytecodealliance:main
from
sansmoraxz:wit-decode/1-limits
Nov 10, 2026
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
108 changes: 108 additions & 0 deletions
108
crates/wit-parser/tests/ui/parse-fail/type-nesting-too-deep-aliases.wit
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how necessary these are per your standards. But keeping as a guard that may be flagged later if the encoder behaviour changes and loop fails. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| // parse-fail | ||
| // | ||
| // Each alias names the previous one, so `t99` is 100 types deep. | ||
|
|
||
| package a:b; | ||
|
|
||
| interface i { | ||
| type t0 = u32; | ||
| type t1 = t0; | ||
| type t2 = t1; | ||
| type t3 = t2; | ||
| type t4 = t3; | ||
| type t5 = t4; | ||
| type t6 = t5; | ||
| type t7 = t6; | ||
| type t8 = t7; | ||
| type t9 = t8; | ||
| type t10 = t9; | ||
| type t11 = t10; | ||
| type t12 = t11; | ||
| type t13 = t12; | ||
| type t14 = t13; | ||
| type t15 = t14; | ||
| type t16 = t15; | ||
| type t17 = t16; | ||
| type t18 = t17; | ||
| type t19 = t18; | ||
| type t20 = t19; | ||
| type t21 = t20; | ||
| type t22 = t21; | ||
| type t23 = t22; | ||
| type t24 = t23; | ||
| type t25 = t24; | ||
| type t26 = t25; | ||
| type t27 = t26; | ||
| type t28 = t27; | ||
| type t29 = t28; | ||
| type t30 = t29; | ||
| type t31 = t30; | ||
| type t32 = t31; | ||
| type t33 = t32; | ||
| type t34 = t33; | ||
| type t35 = t34; | ||
| type t36 = t35; | ||
| type t37 = t36; | ||
| type t38 = t37; | ||
| type t39 = t38; | ||
| type t40 = t39; | ||
| type t41 = t40; | ||
| type t42 = t41; | ||
| type t43 = t42; | ||
| type t44 = t43; | ||
| type t45 = t44; | ||
| type t46 = t45; | ||
| type t47 = t46; | ||
| type t48 = t47; | ||
| type t49 = t48; | ||
| type t50 = t49; | ||
| type t51 = t50; | ||
| type t52 = t51; | ||
| type t53 = t52; | ||
| type t54 = t53; | ||
| type t55 = t54; | ||
| type t56 = t55; | ||
| type t57 = t56; | ||
| type t58 = t57; | ||
| type t59 = t58; | ||
| type t60 = t59; | ||
| type t61 = t60; | ||
| type t62 = t61; | ||
| type t63 = t62; | ||
| type t64 = t63; | ||
| type t65 = t64; | ||
| type t66 = t65; | ||
| type t67 = t66; | ||
| type t68 = t67; | ||
| type t69 = t68; | ||
| type t70 = t69; | ||
| type t71 = t70; | ||
| type t72 = t71; | ||
| type t73 = t72; | ||
| type t74 = t73; | ||
| type t75 = t74; | ||
| type t76 = t75; | ||
| type t77 = t76; | ||
| type t78 = t77; | ||
| type t79 = t78; | ||
| type t80 = t79; | ||
| type t81 = t80; | ||
| type t82 = t81; | ||
| type t83 = t82; | ||
| type t84 = t83; | ||
| type t85 = t84; | ||
| type t86 = t85; | ||
| type t87 = t86; | ||
| type t88 = t87; | ||
| type t89 = t88; | ||
| type t90 = t89; | ||
| type t91 = t90; | ||
| type t92 = t91; | ||
| type t93 = t92; | ||
| type t94 = t93; | ||
| type t95 = t94; | ||
| type t96 = t95; | ||
| type t97 = t96; | ||
| type t98 = t97; | ||
| type t99 = t98; | ||
| } |
5 changes: 5 additions & 0 deletions
5
crates/wit-parser/tests/ui/parse-fail/type-nesting-too-deep-aliases.wit.result
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| type `t99` is nested too deep | ||
| --> tests/ui/parse-fail/type-nesting-too-deep-aliases.wit:107:8 | ||
| | | ||
| 107 | type t99 = t98; | ||
| | ^-- |
108 changes: 108 additions & 0 deletions
108
crates/wit-parser/tests/ui/parse-fail/type-nesting-too-deep-records.wit
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| // parse-fail | ||
| // | ||
| // Each record holds the previous one, so `r99` is 100 types deep. | ||
|
|
||
| package a:b; | ||
|
|
||
| interface i { | ||
| record r0 { x: u32 } | ||
| record r1 { x: r0 } | ||
| record r2 { x: r1 } | ||
| record r3 { x: r2 } | ||
| record r4 { x: r3 } | ||
| record r5 { x: r4 } | ||
| record r6 { x: r5 } | ||
| record r7 { x: r6 } | ||
| record r8 { x: r7 } | ||
| record r9 { x: r8 } | ||
| record r10 { x: r9 } | ||
| record r11 { x: r10 } | ||
| record r12 { x: r11 } | ||
| record r13 { x: r12 } | ||
| record r14 { x: r13 } | ||
| record r15 { x: r14 } | ||
| record r16 { x: r15 } | ||
| record r17 { x: r16 } | ||
| record r18 { x: r17 } | ||
| record r19 { x: r18 } | ||
| record r20 { x: r19 } | ||
| record r21 { x: r20 } | ||
| record r22 { x: r21 } | ||
| record r23 { x: r22 } | ||
| record r24 { x: r23 } | ||
| record r25 { x: r24 } | ||
| record r26 { x: r25 } | ||
| record r27 { x: r26 } | ||
| record r28 { x: r27 } | ||
| record r29 { x: r28 } | ||
| record r30 { x: r29 } | ||
| record r31 { x: r30 } | ||
| record r32 { x: r31 } | ||
| record r33 { x: r32 } | ||
| record r34 { x: r33 } | ||
| record r35 { x: r34 } | ||
| record r36 { x: r35 } | ||
| record r37 { x: r36 } | ||
| record r38 { x: r37 } | ||
| record r39 { x: r38 } | ||
| record r40 { x: r39 } | ||
| record r41 { x: r40 } | ||
| record r42 { x: r41 } | ||
| record r43 { x: r42 } | ||
| record r44 { x: r43 } | ||
| record r45 { x: r44 } | ||
| record r46 { x: r45 } | ||
| record r47 { x: r46 } | ||
| record r48 { x: r47 } | ||
| record r49 { x: r48 } | ||
| record r50 { x: r49 } | ||
| record r51 { x: r50 } | ||
| record r52 { x: r51 } | ||
| record r53 { x: r52 } | ||
| record r54 { x: r53 } | ||
| record r55 { x: r54 } | ||
| record r56 { x: r55 } | ||
| record r57 { x: r56 } | ||
| record r58 { x: r57 } | ||
| record r59 { x: r58 } | ||
| record r60 { x: r59 } | ||
| record r61 { x: r60 } | ||
| record r62 { x: r61 } | ||
| record r63 { x: r62 } | ||
| record r64 { x: r63 } | ||
| record r65 { x: r64 } | ||
| record r66 { x: r65 } | ||
| record r67 { x: r66 } | ||
| record r68 { x: r67 } | ||
| record r69 { x: r68 } | ||
| record r70 { x: r69 } | ||
| record r71 { x: r70 } | ||
| record r72 { x: r71 } | ||
| record r73 { x: r72 } | ||
| record r74 { x: r73 } | ||
| record r75 { x: r74 } | ||
| record r76 { x: r75 } | ||
| record r77 { x: r76 } | ||
| record r78 { x: r77 } | ||
| record r79 { x: r78 } | ||
| record r80 { x: r79 } | ||
| record r81 { x: r80 } | ||
| record r82 { x: r81 } | ||
| record r83 { x: r82 } | ||
| record r84 { x: r83 } | ||
| record r85 { x: r84 } | ||
| record r86 { x: r85 } | ||
| record r87 { x: r86 } | ||
| record r88 { x: r87 } | ||
| record r89 { x: r88 } | ||
| record r90 { x: r89 } | ||
| record r91 { x: r90 } | ||
| record r92 { x: r91 } | ||
| record r93 { x: r92 } | ||
| record r94 { x: r93 } | ||
| record r95 { x: r94 } | ||
| record r96 { x: r95 } | ||
| record r97 { x: r96 } | ||
| record r98 { x: r97 } | ||
| record r99 { x: r98 } | ||
| } |
5 changes: 5 additions & 0 deletions
5
crates/wit-parser/tests/ui/parse-fail/type-nesting-too-deep-records.wit.result
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| type `r99` is nested too deep | ||
| --> tests/ui/parse-fail/type-nesting-too-deep-records.wit:107:10 | ||
| | | ||
| 107 | record r99 { x: r98 } | ||
| | ^-- |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this change there's quite a lot of recursive processing of types in WIT and component-model types in general. This is why the validation of a component limits the depth of types to a fixed amount to ensure that all code downstream which processes types recursively is safe to do so. My guess is that this is not the only location throughout
wit-parserthat uses recursion and doesn't handle deeply-nested types well, and I don't think it's necessarily worthwhile to try to patch every single one of them into a stack.Alternatively, I would personally be more partial to an approach like validation does, which is to basically just validate that types aren't too deep. For example when creating a
Resolveor similar that could verify type depth pretty quickly (in O(types) time). The validation would match what's already a restriction for components anyway, and it would mean that each individual location of recursion throughout thewit-parsercrate doesn't have to get updated.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the usual limits is 100. Going with that.