Workaround issue with Box.unbox causing segfault

Using Box.unbox on a nil value with a union type causes:

Invalid memory access (signal 11) at address 0x8

Related Crystal issue: https://github.com/crystal-lang/crystal/issues/11839
Fixes: https://gitlab.com/arctic-fox/spectator/-/issues/76
This commit is contained in:
Michael Miller 2022-07-18 19:47:34 -06:00
parent 95764140ee
commit 18e9c1c35d
No known key found for this signature in database
GPG key ID: 32B47AE8F388A1FF
3 changed files with 22 additions and 2 deletions

View file

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- Workaround nilable type issue with memoized value. [#76](https://gitlab.com/arctic-fox/spectator/-/issues/76)
## [0.11.0] - 2022-07-14
### Changed
- Overhauled mock and double system. [#63](https://gitlab.com/arctic-fox/spectator/-/issues/63)

View file

@ -0,0 +1,6 @@
require "../spec_helper"
Spectator.describe "GitLab Issue #76" do
let(:value) { nil.as(Int32?) }
specify { expect(value).to be_nil }
end

View file

@ -19,7 +19,12 @@ module Spectator
# Retrieves the previously wrapped value.
# The *type* of the wrapped value must match otherwise an error will be raised.
def get(type : T.class) : T forall T
Box(T).unbox(@pointer)
{% begin %}
{% if T.nilable? %}
@pointer.null? ? nil :
{% end %}
Box(T).unbox(@pointer)
{% end %}
end
# Retrieves the previously wrapped value.
@ -34,7 +39,12 @@ module Spectator
# type = wrapper.get { Int32 } # Returns Int32
# ```
def get(& : -> T) : T forall T
Box(T).unbox(@pointer)
{% begin %}
{% if T.nilable? %}
@pointer.null? ? nil :
{% end %}
Box(T).unbox(@pointer)
{% end %}
end
end
end