-
Notifications
You must be signed in to change notification settings - Fork 8
Add an option to annotate paths for inlined modules #17
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
base: master
Are you sure you want to change the base?
Conversation
|
Getting caught up on all my GH notifications, but wanted to acknowledge seeing the PR. I'll get a review up tomorrow morning. |
|
thank you! :) |
TedDriggs
left a comment
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.
This is looking really good; I'm now really curious to know what project you're working on that needs it.
There is one more change that I think is warranted but I couldn't leave a comment on because it's outside the edited ranges: You deserve to be listed as an author of the crate :) If you'd like to be included just put yourself in on the next commit.
| let mut path = None; | ||
| let position = attrs.iter().position(|attr| { | ||
| if attr.path.is_ident(SYN_INLINE_MOD_PATH) { | ||
| // Ignore the attribute if it isn't of the correct form. |
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.
Is your worry here that some other proc-macro might happen to squat on our attribute name? Finding an attribute of the right name and wrong format feels to me like something must have gone horribly wrong.
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.
Yeah or the user puts the annotation in themselves or something. The options are to panic or ignore -- what do you think about them? I guess panicking is probably better/safer since it'd be totally unexpected to hit this.
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.
Well I realized this may end up dealing with external data so we'd probably rather not panic. I think this should be a pretty rare case though, as you pointed out something's really gone wrong (but we don't want to create an opportunity for an accidental DoS).
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.
DoS seems bad, but if you're dealing with untrusted input couldn't someone put that attribute into the original source code to try and make you follow a path into a directory you shouldn't?
I'm wondering if embedding these in-band is fundamentally unsafe.
I think this can be done safely, but we should explicitly disallow inlining if the input contains the magic attribute in the inner or outer attributes. That way we avoid attacks that attempt to feed us incorrect paths; those sorts of attack could be used to try and read arbitrary files from wherever this code was being run.
If we need to support the same code being inlined multiple times, then I see two options:
- We only fail inlining if the attribute is present and we've been asked to add path annotations. One upside of this approach is that we don't do work scanning attributes unless we're anticipating using the inserted annotations, while a downside of this approach is that someone could still sneak a bad path through because there's no connection between
find_mod_pathandInliningResult - Rather than being a constant, the attribute path is a property of
InlininerBuilderand later ofInliningResult. That seems pretty ugly, however, especially since that would meanfind_mod_pathshould take(r: &InliningResult, attributes: &[Attribute])to avoid callers from hardcoding what they thought the attribute name was in their own code.
A bit of a long-winded explanation, sorry!
|
Add an option to `InlinerBuilder`, defaulting to `false`, which causes `syn-inline-mod` to annotate inlined modules with the paths they come from. This is useful when mapping spans back to the files they come from.
TedDriggs
left a comment
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.
Thanks for making those changes. This is looking even better, but your comment about untrusted input made me look at this through more paranoid eyes.
| let mut path = None; | ||
| let position = attrs.iter().position(|attr| { | ||
| if attr.path.is_ident(SYN_INLINE_MOD_PATH) { | ||
| // Ignore the attribute if it isn't of the correct form. |
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.
DoS seems bad, but if you're dealing with untrusted input couldn't someone put that attribute into the original source code to try and make you follow a path into a directory you shouldn't?
I'm wondering if embedding these in-band is fundamentally unsafe.
I think this can be done safely, but we should explicitly disallow inlining if the input contains the magic attribute in the inner or outer attributes. That way we avoid attacks that attempt to feed us incorrect paths; those sorts of attack could be used to try and read arbitrary files from wherever this code was being run.
If we need to support the same code being inlined multiple times, then I see two options:
- We only fail inlining if the attribute is present and we've been asked to add path annotations. One upside of this approach is that we don't do work scanning attributes unless we're anticipating using the inserted annotations, while a downside of this approach is that someone could still sneak a bad path through because there's no connection between
find_mod_pathandInliningResult - Rather than being a constant, the attribute path is a property of
InlininerBuilderand later ofInliningResult. That seems pretty ugly, however, especially since that would meanfind_mod_pathshould take(r: &InliningResult, attributes: &[Attribute])to avoid callers from hardcoding what they thought the attribute name was in their own code.
|
|
||
| match visitor.visit() { | ||
| Ok(syn::File { attrs, items, .. }) => { | ||
| if self.annotate_paths { |
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.
To the comment above, I wonder if we should check here that no attribute in the input is using our path, returning an error if it is?
| /// | ||
| /// If this is `true`, `find_mod_path` may be used to figure out the path a module is defined | ||
| /// in. | ||
| pub fn paths_annotated(&self) -> bool { |
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.
How would you feel about this being called has_path_annotations? In my opinion that makes it clearer this is describing the current state of something.
|
Thanks for the great explanation of what you're up to - that's helpful for me when thinking about the long-term evolution of this crate. |
|
|
||
| /// A module path in a list of attributes, found by `find_mod_path`. | ||
| #[derive(Clone, Debug)] | ||
| pub struct InlineModPath<'ast> { |
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.
Should this be called InlineModAttributes and have path: Option<PathBuf> as a field? Then the find_mod_path function would be changed to split_mod_attributes(attrs: &[Attribute]) -> InlineModAttributes {}.
|
Just wanted to say that this is in my queue of things to do, but I have personal life stuff going on at the moment which make it unlikely I can revisit this before mid-August. Thanks! |
|
@sunshowers sorry to hear that. If I have time I'll see if I can move it forward - would you like me to block merging on your review of any subsequent changes I make? |
|
Thanks -- it would be lovely if you could give me a day or so to respond, but please don't block on me if I don't get to it by then! |
Depends on #16.
Add an option to
InlinerBuilder, defaulting tofalse, which causessyn-inline-modto annotate inlined modules with the paths they come from.This is useful when mapping spans back to the files they come from.
(There's a fair bit of added complexity here. I'd totally understand if you
don't want to accept this, but this is essential to the work I'm doing so I'd
unfortunately have to fork the crate in that case.)
Closes #15.