Ignore inherited methods in BinData field-name guard (#261)#300
Open
arpitjain099 wants to merge 1 commit into
Open
Ignore inherited methods in BinData field-name guard (#261)#300arpitjain099 wants to merge 1 commit into
arpitjain099 wants to merge 1 commit into
Conversation
BinData rejects a field name when a method of that name is already defined on the struct class. The check in DSLFieldValidator used Module#method_defined? without the second argument, so it also matched methods inherited from ancestors such as Object, Kernel and Hash. When a mocking library is loaded before ruby_smb (for example rspec-mocks adds Object#stub under config.mock_with :rspec), valid BinData definitions started raising SyntaxError: field 'stub' shadows an existing method even though RubySMB::Dcerpc::Request legitimately defines a :stub field. Field accessors are installed per instance with define_singleton_method, so an inherited method named like a field never collides at runtime; only a method defined directly on the struct class is a real collision. Passing false to method_defined? restricts the guard to directly-defined methods. Names that clash with Hash/BinData internals stay covered by the separate BinData::Struct::RESERVED list, so that protection is unchanged. The fix is a small compatibility shim required right after bindata, plus a regression spec covering the inherited-method, direct-method and reserved-name cases. Fixes rapid7#261 Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Fixes #261.
Problem
Loading
ruby_smbafter a mocking library has patchedObjectraises aSyntaxErrorfrom BinData while the gem's own struct definitions are beingbuilt:
The common trigger is an RSpec suite configured with
config.mock_with :rspec,because rspec-mocks adds a
#stubhelper toBasicObject/Object. If thathappens before
require 'ruby_smb'(a normalspec_helper.rbordering), theinherited
#stubcollides with the legitimate:stubfield onRubySMB::Dcerpc::Request.The root cause is in BinData's field-name guard
(
BinData::DSLMixin::DSLFieldValidator#name_shadows_method?), which calls@the_class.method_defined?(name). Without the second argument,method_defined?also returnstruefor methods inherited from ancestors suchas
Object,KernelandHash, so any field whose name matches an inheritedhelper method is wrongly rejected.
Fix
This adds a small compatibility shim (
lib/ruby_smb/compatibility.rb, requiredimmediately after
require 'bindata') that narrows the guard to@the_class.method_defined?(name, false). Thefalserestricts the check tomethods defined directly on the struct class, which is what the guard is meant
to enforce.
Why this does not weaken the guard:
define_singleton_method, soan inherited method that happens to share a field's name never gets in the way
at runtime. Only a method defined directly on the struct class is a genuine
collision, and that case still raises.
Hashmethods or BinData DSL internals are handled by aseparate, independent check (
name_is_reserved?againstBinData::Struct::RESERVED). That list is unchanged, so reserved names such askeysstill raise.This is purely a compatibility/loosening of which field names are accepted. It
does not rename, retype, or otherwise change any BinData data definition, so the
versioning note in CONTRIBUTING.md (minor bump on BinData definition changes)
does not apply here.
Tests
spec/lib/ruby_smb/compatibility_spec.rbcovers all three branches:(the Field 'stub' shadows an existing method in RubySMB::Dcerpc::Request while unit testing #261 regression),
keys) still raises.Verification Steps
bundle installrake specrake specManual scenario