https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112020-08-28T21:35:02ZRuby Issue Tracking SystemRuby master - Bug #16983: RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in evalhttps://redmine.ruby-lang.org/issues/16983?journal_id=872632020-08-28T21:35:02Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>I'm not sure if this is a bug, but it does seem like a fundamental and significant limitation with the design of RubyVM::AbstractSyntaxTree.of. RubyVM::AbstractSyntaxTree.of reparses the file the method is defined in and cannot handle any cases where <code>eval</code> or similar are used. You'll get a node completely different from what you would expect. Here's another example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">eval</span> <span class="no">DATA</span><span class="p">.</span><span class="nf">read</span><span class="p">,</span> <span class="nb">binding</span><span class="p">,</span> <span class="kp">__FILE__</span><span class="p">,</span> <span class="mi">14</span>
<span class="nb">method</span> <span class="o">=</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:foo</span><span class="p">)</span>
<span class="n">pp</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">AbstractSyntaxTree</span><span class="p">.</span><span class="nf">of</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
<span class="cp">__END__
def foo
end
</span></code></pre>
<p>Output:</p>
<pre><code>(VCALL@1:16-1:23 :binding)
</code></pre>
<p>Because it reparses the file, you'll also get the wrong result if the file is modified:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">bar</span>
<span class="k">end</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="kp">__FILE__</span><span class="p">,</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="kp">__FILE__</span><span class="p">).</span><span class="nf">gsub</span><span class="p">(</span><span class="s1">'def bar'</span><span class="p">,</span> <span class="s2">"def foo</span><span class="se">\n</span><span class="s2">bar"</span><span class="p">))</span>
<span class="nb">method</span> <span class="o">=</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:bar</span><span class="p">)</span>
<span class="n">pp</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">AbstractSyntaxTree</span><span class="p">.</span><span class="nf">of</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
</code></pre>
<p>Output:</p>
<pre><code>(SCOPE@1:0-3:3
tbl: []
args:
(ARGS@1:7-1:7
pre_num: 0
pre_init: nil
opt: nil
first_post: nil
post_num: 0
post_init: nil
rest: nil
kw: nil
kwrest: nil
block: nil)
body: (VCALL@2:0-2:3 :bar))
</code></pre>
<p>And if the interpreter can no longer access the file (chroot, file deletion, permission change, or other file system access limiting), you get an error.</p>
<p>I can't think of a way to fix this without all iseq methods holding a reference to the string used to parse them, and having RubyVM::AbstractSyntaxTree.of work off that string. I'm not sure how much extra memory use that would cause, or if such an approach is considered acceptable.</p> Ruby master - Bug #16983: RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in evalhttps://redmine.ruby-lang.org/issues/16983?journal_id=915882021-04-17T07:21:16Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>ko1 (Koichi Sasada)</i></li></ul><p>This ticket was discussed on dev-meeting. A method (or proc) created in an <code>eval</code> context should be marked and <code>AST.of</code> should raise an exception against a marked method. <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/17">@ko1 (Koichi Sasada)</a> said that he will do.</p> Ruby master - Bug #16983: RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in evalhttps://redmine.ruby-lang.org/issues/16983?journal_id=920892021-05-21T19:11:45Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>Because I know how busy <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/17">@ko1 (Koichi Sasada)</a> is, I thought I'd save him some work and tried to implement this myself: <a href="https://github.com/ruby/ruby/pull/4519" class="external">https://github.com/ruby/ruby/pull/4519</a></p> Ruby master - Bug #16983: RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in evalhttps://redmine.ruby-lang.org/issues/16983?journal_id=930552021-07-29T20:51:24Zjeremyevans (Jeremy Evans)code@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>Applied in changeset <a class="changeset" title="Make RubyVM::AbstractSyntaxTree.of raise for method/proc created in eval This changes Thread::Lo..." href="https://redmine.ruby-lang.org/projects/ruby-master/repository/git/revisions/64ac984129a7a4645efe5ac57c168ef880b479b2">git|64ac984129a7a4645efe5ac57c168ef880b479b2</a>.</p>
<hr>
<p>Make RubyVM::AbstractSyntaxTree.of raise for method/proc created in eval</p>
<p>This changes Thread::Location::Backtrace#absolute_path to return<br>
nil for methods/procs defined in eval. If the realpath of an iseq<br>
is nil, that indicates it was defined in eval, in which case you<br>
cannot use RubyVM::AbstractSyntaxTree.of.</p>
<p>Fixes [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in eval (Closed)" href="https://redmine.ruby-lang.org/issues/16983">#16983</a>]</p>
<p>Co-authored-by: Koichi Sasada <a href="mailto:ko1@atdot.net" class="email">ko1@atdot.net</a></p>