-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fix Log::Metadata#dup
crash with 2+ entries
#13369
Fix Log::Metadata#dup
crash with 2+ entries
#13369
Conversation
Log::Metadata
crash with 2+ entriesLog::Metadata#dup
crash with 2+ entries
@@ -28,6 +28,14 @@ describe Log::Metadata do | |||
m({a: 1}).extend({} of Symbol => String).should_not be_empty | |||
end | |||
|
|||
describe "#dup" do | |||
it "creates a shallow copy" do | |||
Log::Metadata.empty.dup.should eq(Log::Metadata.empty) |
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.
Shouldn't this use:
Log::Metadata.empty.dup.should eq(Log::Metadata.empty) | |
Log::Metadata.empty.dup.should be(Log::Metadata.empty) |
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.
I think this would be testing .empty
more than #dup
... But yeah technically, all expectations could use be
. But I think that's actually an implementation detail. It's not strictly necessary for #dup
to return the same instance, but it does that for performance reasons.
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.
It isn't part of #dup
's contract to preserve object identity of immutable reference types, one day #dup
might create a shallow copy for other reasons. So eq
suffices for unit tests of #dup
All reference types have a default
#dup
implementation that allocates new storage with size equal toinstance_sizeof(self)
.Log::Metadata
uses custom allocation and instances with 2 or more entries are larger than that size, but the default#dup
only copies the first entry, so anything after that is uninitialized memory and can lead to crashes: (in this case:unchecked
probably comes from the symbol's internal ID, used inMutex
)Since
Log::Metadata
is immutable,#dup
can be a no-op. A true shallow copy would have been: