Skip to content

Commit 28d6e45

Browse files
committed
Fix comparing and disallow passing functions/mixins across compilations
1 parent c05a8f5 commit 28d6e45

File tree

4 files changed

+35
-13
lines changed

4 files changed

+35
-13
lines changed

lib/sass/compiler/host/function_registry.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ class Host
77
#
88
# It stores sass custom functions and handles function calls.
99
class FunctionRegistry
10-
attr_reader :global_functions
10+
attr_reader :environment, :global_functions
1111

1212
def initialize(functions, alert_color:)
1313
functions = functions.transform_keys(&:to_s)
1414

15+
@environment = BasicObject.new
1516
@global_functions = functions.keys
1617
@functions_by_name = functions.transform_keys do |signature|
1718
index = signature.index('(')

lib/sass/compiler/host/protofier.rb

+23-8
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ def to_proto(obj)
6464
)
6565
when Sass::Value::Function
6666
if obj.instance_variable_defined?(:@id)
67+
assert_compiler_value(obj)
68+
6769
EmbeddedProtocol::Value.new(
6870
compiler_function: EmbeddedProtocol::Value::CompilerFunction.new(
6971
id: obj.instance_variable_get(:@id)
@@ -78,6 +80,8 @@ def to_proto(obj)
7880
)
7981
end
8082
when Sass::Value::Mixin
83+
assert_compiler_value(obj)
84+
8185
EmbeddedProtocol::Value.new(
8286
compiler_mixin: EmbeddedProtocol::Value::CompilerMixin.new(
8387
id: obj.instance_variable_get(:@id)
@@ -148,17 +152,11 @@ def from_proto(proto)
148152
end
149153
)
150154
when :compiler_function
151-
Sass::Value::Function.allocate.instance_eval do
152-
@id = obj.id
153-
self
154-
end
155+
compiler_value(Sass::Value::Function, obj.id)
155156
when :host_function
156157
raise Sass::ScriptError, 'The compiler may not send Value.host_function to host'
157158
when :compiler_mixin
158-
Sass::Value::Mixin.allocate.instance_eval do
159-
@id = obj.id
160-
self
161-
end
159+
compiler_value(Sass::Value::Mixin, obj.id)
162160
when :calculation
163161
Calculation.from_proto(obj)
164162
when :singleton
@@ -177,6 +175,23 @@ def from_proto(proto)
177175
end
178176
end
179177

178+
private
179+
180+
def assert_compiler_value(value)
181+
unless value.instance_variable_get(:@environment) == @function_registry.environment
182+
raise Sass::ScriptError, "#{value} does not belong to this compilation"
183+
end
184+
185+
value
186+
end
187+
188+
def compiler_value(klass, id)
189+
value = klass.allocate
190+
value.instance_variable_set(:@environment, @function_registry.environment)
191+
value.instance_variable_set(:@id, id)
192+
value
193+
end
194+
180195
# The {Number} Protofier.
181196
module Number
182197
module_function

lib/sass/value/function.rb

+6-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ def initialize(signature, &callback)
1515
@callback = callback.freeze
1616
end
1717

18+
# @return [Object, nil]
19+
protected attr_reader :environment
20+
1821
# @return [Integer, nil]
1922
protected attr_reader :id
2023

@@ -26,10 +29,10 @@ def initialize(signature, &callback)
2629

2730
# @return [::Boolean]
2831
def ==(other)
29-
if id.nil?
30-
other.equal?(self)
32+
if defined?(@id)
33+
other.is_a?(Sass::Value::Function) && other.environment == environment && other.id == id
3134
else
32-
other.is_a?(Sass::Value::Function) && other.id == id
35+
other.equal?(self)
3336
end
3437
end
3538

lib/sass/value/mixin.rb

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ class << self
1212
private :new
1313
end
1414

15+
# @return [Object]
16+
protected attr_reader :environment
17+
1518
# @return [Integer]
1619
protected attr_reader :id
1720

1821
# @return [::Boolean]
1922
def ==(other)
20-
other.is_a?(Sass::Value::Mixin) && other.id == id
23+
other.is_a?(Sass::Value::Mixin) && other.environment == environment && other.id == id
2124
end
2225

2326
# @return [Integer]

0 commit comments

Comments
 (0)