https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112011-03-29T20:06:26ZRuby Issue Tracking SystemRuby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=162412011-03-29T20:06:26Zryanlecompte (Ryan LeCompte)lecompte@gmail.com
<ul></ul><p>The following fails with a failure to call "<code>x=</code>" private method</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">String</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:attr_accessor</span><span class="p">,</span> <span class="ss">:x</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="s2">""</span>
<span class="n">s</span><span class="p">.</span><span class="nf">x</span> <span class="o">=</span> <span class="mi">100</span>
</code></pre>
<p>The following works:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">String</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:attr_accessor</span><span class="p">,</span> <span class="ss">:x</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">s</span> <span class="o">=</span> <span class="s2">""</span>
<span class="n">s</span><span class="p">.</span><span class="nf">x</span> <span class="o">=</span> <span class="mi">100</span>
</code></pre> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=184512011-06-26T18:45:28Znaruse (Yui NARUSE)naruse@airemix.jp
<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> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=184622011-06-26T18:59:20Zko1 (Koichi Sasada)
<ul><li><strong>Category</strong> set to <i>core</i></li><li><strong>Target version</strong> set to <i>2.0.0</i></li></ul><p>Behavior: It inherits current visibility (visibility of top-level is "private"). 1.8 also causes an exception. It seems to be a spec.</p>
<p>However, the following code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">::</span><span class="no">String</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:define_method</span><span class="p">,</span> <span class="ss">:x</span><span class="o">=</span><span class="p">){</span><span class="o">|</span><span class="n">v</span><span class="o">|</span><span class="p">}</span>
<span class="n">s</span> <span class="o">=</span> <span class="s1">''</span>
<span class="n">s</span><span class="p">.</span><span class="nf">x</span> <span class="o">=</span> <span class="mi">100</span>
</code></pre>
<p>doesn't cause an exception. It seems to be an inconsistency.</p>
<p>The following code doesn't cause an exception on 1.9 and 1.8:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">C</span>
<span class="kp">private</span>
<span class="o">::</span><span class="no">String</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:define_method</span><span class="p">,</span> <span class="ss">:x</span><span class="o">=</span><span class="p">){</span><span class="o">|</span><span class="n">v</span><span class="o">|</span><span class="p">}</span>
<span class="k">end</span>
<span class="n">s</span> <span class="o">=</span> <span class="s1">''</span>
<span class="n">s</span><span class="p">.</span><span class="nf">x</span> <span class="o">=</span> <span class="mi">100</span>
</code></pre>
<p>However, the following code causes an exception only on 1.8:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">C</span>
<span class="kp">private</span>
<span class="n">define_method</span><span class="p">(</span><span class="ss">:x</span><span class="o">=</span><span class="p">){</span><span class="o">|</span><span class="n">v</span><span class="o">|</span><span class="p">}</span>
<span class="k">end</span>
<span class="no">C</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">x</span> <span class="o">=</span> <span class="mi">10</span>
</code></pre>
<p>I can't understand how should it be.</p>
<p>Possible solutions:</p>
<p>(1) Remain it as spec.<br>
(2) All "attr_*" methods define all methods in public.<br>
(3) others?</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=339062012-11-26T09:19:37Zko1 (Koichi Sasada)
<ul><li><strong>Target version</strong> changed from <i>2.0.0</i> to <i>2.6</i></li></ul><p>No discussion.</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=602502016-08-23T22:50:19Zbughit (bug hit)
<ul></ul><p>why should top level visibility (which applies to methods defined in the Object class) have any effect on other classes?</p>
<p>this also applies to any other module which you might be in</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Class1</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">SomeUnrelatedModule</span>
<span class="no">Class1</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:attr_accessor</span><span class="p">,</span> <span class="ss">:public_attr</span><span class="p">)</span>
<span class="kp">private</span>
<span class="no">Class1</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:attr_accessor</span><span class="p">,</span> <span class="ss">:private_attr</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">c1</span> <span class="o">=</span> <span class="no">Class1</span><span class="p">.</span><span class="nf">new</span>
<span class="n">c1</span><span class="p">.</span><span class="nf">public_attr</span>
<span class="n">c1</span><span class="p">.</span><span class="nf">private_attr</span>
</code></pre>
<p>what does visibility in SomeUnrelatedModule have to do with methods defined in Class1?</p>
<p>methods defined on a given target module when the default definee at the point of definition is not the target module, should be public, since that's the default visibility</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Class1</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:define_method</span><span class="p">,</span> <span class="ss">:foo</span><span class="p">)</span> <span class="p">{}</span>
</code></pre>
<p>defines a public method</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Class1</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:attr_accessor</span><span class="p">,</span> <span class="ss">:foo</span><span class="p">)</span>
</code></pre>
<p>should too</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=602522016-08-23T23:10:35Zbughit (bug hit)
<ul></ul><p>define_method used to have the same (or similar) problem<br>
<a href="https://bugs.ruby-lang.org/issues/9005" class="external">https://bugs.ruby-lang.org/issues/9005</a></p>
<p>which was fixed, so why shouldn't this be?</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=603172016-08-29T16:29:18Zbughit (bug hit)
<ul><li><strong>Assignee</strong> changed from <i>ko1 (Koichi Sasada)</i> to <i>nobu (Nobuyoshi Nakada)</i></li></ul><p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/4">@nobu (Nobuyoshi Nakada)</a> shouldn't this get the same treatment as <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: object.send(:define_method, ...){...} creates private method (Closed)" href="https://bugs.ruby-lang.org/issues/9005">#9005</a></p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=608322016-10-11T08:39:46Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>ruby -v</strong> changed from <i>ruby 1.9.2p180 (2011-02-18 revision 30907) [x86_64-darwin10.7.0]</i> to <i>ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]</i></li></ul> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=608332016-10-11T08:40:42Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Closed</i> to <i>Assigned</i></li><li><strong>Assignee</strong> changed from <i>nobu (Nobuyoshi Nakada)</i> to <i>ko1 (Koichi Sasada)</i></li></ul> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=608462016-10-11T11:11:02Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul></ul><p>Just FYI we looked at it in developer meeting today and agreed this is a bug that have yet to be fixed.</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=627692017-01-31T09:04:10Zko1 (Koichi Sasada)
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/62769/diff?detail_id=43819">diff</a>)</li></ul> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=627702017-01-31T09:10:02Zko1 (Koichi Sasada)
<ul></ul><p>So we should choose</p>
<blockquote>
<p>(2) All "attr_*" methods define all methods in public.</p>
</blockquote>
<p>(on #3), right?</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=803172019-08-01T00:16:07Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>File</strong> <a href="/attachments/7925">attr-visibility-4537.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/7925/attr-visibility-4537.patch">attr-visibility-4537.patch</a> added</li></ul><p>Attached is a patch that makes attr* methods handle visibility the same as <code>define_method</code>, using the approach nobu developed for <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: object.send(:define_method, ...){...} creates private method (Closed)" href="https://bugs.ruby-lang.org/issues/9005">#9005</a>. I think this behavior makes the most sense. Always defining attr* methods as public (approach (2)) breaks backwards compatibility in more cases, and could lead to security issues in cases where public methods are treated differently than private methods in regards to how user input is handled.</p> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=803252019-08-01T08:21:03Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/80325/diff?detail_id=54023">diff</a>)</li></ul><p>Seems fine.</p>
<p>BTW, it doesn't need to be the global <code>String</code>.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index cdc084c8bc..9e57692ca0 100644
</span><span class="gd">--- a/test/ruby/test_module.rb
</span><span class="gi">+++ b/test/ruby/test_module.rb
</span><span class="p">@@ -706,13 +706,16 @@</span>
end
def test_attr_public_at_toplevel
<span class="gd">- eval(<<-END, TOPLEVEL_BINDING)
- String.send(:attr_accessor, :x)
- String.send(:attr, :y)
- String.send(:attr_reader, :z)
- String.send(:attr_writer, :w)
</span><span class="gi">+ s = Object.new
+ TOPLEVEL_BINDING.eval(<<-END).call(s.singleton_class)
+ proc do |c|
+ c.send(:attr_accessor, :x)
+ c.send(:attr, :y)
+ c.send(:attr_reader, :z)
+ c.send(:attr_writer, :w)
+ end
</span> END
<span class="gd">- s = ""
</span><span class="gi">+
</span> assert_nil s.x
s.x = 1
assert_equal 1, s.x
<span class="p">@@ -727,10 +730,6 @@</span>
s.w = 4
assert_equal 4, s.instance_variable_get(:@w)
<span class="gd">- ensure
- [:x, :x=, :y, :z, :w=].each do |meth|
- String.undef_method(meth) rescue nil
- end
</span> end
def test_const_get_evaled
</code></pre> Ruby master - Bug #4537: Incorrectly creating private method via attr_accessorhttps://bugs.ruby-lang.org/issues/4537?journal_id=803322019-08-01T15:55:09Zjeremyevans (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 attr* methods define public methods if self in caller is not same as receiver Previously, a..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/ef45a57801a2ae8621b0cde59f11159f89f0a8dc">git|ef45a57801a2ae8621b0cde59f11159f89f0a8dc</a>.</p>
<hr>
<p>Make attr* methods define public methods if self in caller is not same as receiver</p>
<p>Previously, attr* methods could be private even if not in the<br>
private section of a class/module block.</p>
<p>This uses the same approach that ruby started using for define_method<br>
in 1fc33199736f316dd71d0c551edbf514528ddde6.</p>
<p>Fixes [Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Incorrectly creating private method via attr_accessor (Closed)" href="https://bugs.ruby-lang.org/issues/4537">#4537</a>]</p>