Skip to content
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

RuntimeError: out of bounds memory access when using plugin on a large nested AST #9782

Open
jzhan-canva opened this issue Dec 3, 2024 · 12 comments
Labels
Milestone

Comments

@jzhan-canva
Copy link
Contributor

jzhan-canva commented Dec 3, 2024

Describe the bug

When a large nested file being loaded to swc with plugin, the plugin_runner will crash.
When same file being loaded to swc without plugin, no error is thrown.

Input code

export result = {
      output: outputBuilder()
        .addConfig(1)
        .addConfig(2)
        .addConfig(3)
        .addConfig(4)
        .addConfig(5)
        ....
        .addConfig(1500)
        .build(),
    }

Config

{
  "$schema": "https://swc.rs/schema.json",
  "jsc": {
    "experimental": {
      "plugins": [["@swc/plugin-noop", {}]]
    }
  }
}

Playground link (or link to the minimal reproduction)

https://github.com/jzhan-canva/swc-plugin-bug

SWC Info output

No response

Expected behavior

Same a running swc without plugin, that it should run

Actual behavior

Crash
image

Version

"@swc/cli": "^0.5.2", "@swc/core": "^1.9.3", "@swc/plugin-noop": "^5.0.0"

Additional context

No response

@kdy1 kdy1 added this to the Planned milestone Dec 3, 2024
@jzhan-canva
Copy link
Contributor Author

jzhan-canva commented Dec 4, 2024

upon further investigation, it seems the bug only happen when AST tree is too deep, not the breadth
for example in the reproducible example, I have a builder with 1000+ depth member expression, and it trigger the issue
but if I reduce depth, I can duplicate the builder code many times without any issue

@kdy1
Copy link
Member

kdy1 commented Dec 4, 2024

So my guess is that it's about stack overflow rather than a memory usage. Stack sizes are limited, and I think rkyv is failing due to the nested call level being too deep.

@kwonoj
Copy link
Member

kwonoj commented Dec 4, 2024

I believe we have same issues in the host as well? if depth is deep enough, either host or plugin won't able to traverse down with visitor.

@jzhan-canva
Copy link
Contributor Author

Right now the host and guest have different limit. I think it makes sense to have same limit for host and guest

@jzhan-canva
Copy link
Contributor Author

Current host limit is bigger, so the identical file can run without plugin but not with plugin

@kwonoj
Copy link
Member

kwonoj commented Dec 4, 2024

I think it makes sense to have same limit for host and guest

I'm not sure if this is configurable on our end, ideally hope to do so.

@kdy1
Copy link
Member

kdy1 commented Dec 4, 2024

No, I mean it's failing with rkyv. The example plugin does not visit the program.

@jzhan-canva
Copy link
Contributor Author

I can find this similar issue #1627 and it was resolved by #8867
maybe this maybe_grow_default is needed in rkyv as well?

@jzhan-canva
Copy link
Contributor Author

jzhan-canva commented Dec 9, 2024

I'm able to reproduce this issue in a unit test
image

@bradzacher
Copy link

bradzacher commented Jan 7, 2025

is there a way that we can workaround this?
for example -- could we pull in SWC into a rust crate to include the plugin natively, rather than as WASM? is there a supported existing pathway for creating a "SWC with custom plugins" build?

@kdy1
Copy link
Member

kdy1 commented Jan 7, 2025

@bradzacher Yes, and I'm actively maintaining it, although it's not in the current repository and there's no clean API for it as it's not designed for a general use.
next-swc is @swc/core with some css-in-js plugins.

The base code of a custom SWC binary with transform() lives at https://github.com/swc-project/swc/blob/5a584078645b8d62df5591a1938be3f0d669c544/bindings/binding_core_node/src/transform.rs and next-swc defines a function named custom_before_pass, and creates a sequence of all custom passes. https://github.com/vercel/next.js/blob/5f455e1a9533f8a29076a30edbaf87a0cccdcdc0/crates/next-custom-transforms/src/chain_transforms.rs#L121-L329

After declaring your own chain of the custom passes, you can pass it to process_js_with_custom_pass like https://github.com/vercel/next.js/blob/5f455e1a9533f8a29076a30edbaf87a0cccdcdc0/crates/napi/src/transform.rs#L138-L147

@kdy1
Copy link
Member

kdy1 commented Jan 7, 2025

@bradzacher Please tell me if you need more guidance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants