Skip to content

Commit 7454333

Browse files
committed
Require pin variable when accessing variable inside binary size in match, closes #12588
1 parent be9dc8a commit 7454333

20 files changed

+64
-58
lines changed

lib/elixir/lib/base.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ defmodule Base do
634634

635635
defp unquote(name)(string, pad?) do
636636
segs = div(byte_size(string) + 7, 8) - 1
637-
<<main::size(segs)-binary-unit(64), rest::binary>> = string
637+
<<main::size(^segs)-binary-unit(64), rest::binary>> = string
638638

639639
main =
640640
for <<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8 <- main>>, into: <<>> do
@@ -1107,7 +1107,7 @@ defmodule Base do
11071107

11081108
defp unquote(name)(string, pad?) do
11091109
segs = div(byte_size(string) + 7, 8) - 1
1110-
<<main::size(segs)-binary-unit(64), rest::binary>> = string
1110+
<<main::size(^segs)-binary-unit(64), rest::binary>> = string
11111111

11121112
main =
11131113
for <<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8 <- main>>, into: <<>> do

lib/elixir/lib/inspect.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ defimpl Inspect, for: BitString do
208208

209209
defp each_bit(bitstring, _counter, opts) do
210210
size = bit_size(bitstring)
211-
<<h::size(size)>> = bitstring
211+
<<h::size(^size)>> = bitstring
212212
concat(Inspect.Integer.inspect(h, opts), "::size(" <> Integer.to_string(size) <> ")")
213213
end
214214

lib/elixir/lib/kernel.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4783,7 +4783,7 @@ defmodule Kernel do
47834783
part
47844784
else
47854785
<<first_byte, rest::binary>> = part
4786-
for <<_::size(step - 1)-bytes, byte <- rest>>, into: <<first_byte>>, do: <<byte>>
4786+
for <<_::size(^step - 1)-bytes, byte <- rest>>, into: <<first_byte>>, do: <<byte>>
47874787
end
47884788
else
47894789
""

lib/elixir/lib/kernel/special_forms.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ defmodule Kernel.SpecialForms do
249249
The size can be a variable or any valid guard expression:
250250
251251
iex> name_size = 5
252-
iex> <<name::binary-size(name_size), " the ", species::binary>> = <<"Frank the Walrus">>
252+
iex> <<name::binary-size(^name_size), " the ", species::binary>> = <<"Frank the Walrus">>
253253
iex> {name, species}
254254
{"Frank", "Walrus"}
255255

lib/elixir/lib/regex.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ defmodule Regex do
601601
new_offset = pos + length
602602
keep = pos - offset
603603

604-
<<_::binary-size(offset), part::binary-size(keep), match::binary-size(length), _::binary>> =
604+
<<_::binary-size(^offset), part::binary-size(^keep), match::binary-size(^length), _::binary>> =
605605
string
606606

607607
if keep == 0 and trim do
@@ -618,7 +618,7 @@ defmodule Regex do
618618
if keep == 0 and trim do
619619
do_split([h | t], string, new_offset, counter, trim, false)
620620
else
621-
<<_::binary-size(offset), part::binary-size(keep), _::binary>> = string
621+
<<_::binary-size(^offset), part::binary-size(^keep), _::binary>> = string
622622
[part | do_split([h | t], string, new_offset, counter - 1, trim, false)]
623623
end
624624
end
@@ -748,12 +748,12 @@ defmodule Regex do
748748
defp apply_list(whole, string, pos, replacement, [[{mpos, _} | _] | _] = list)
749749
when mpos > pos do
750750
length = mpos - pos
751-
<<untouched::binary-size(length), rest::binary>> = string
751+
<<untouched::binary-size(^length), rest::binary>> = string
752752
[untouched | apply_list(whole, rest, mpos, replacement, list)]
753753
end
754754

755755
defp apply_list(whole, string, pos, replacement, [[{pos, length} | _] = head | tail]) do
756-
<<_::size(length)-binary, rest::binary>> = string
756+
<<_::size(^length)-binary, rest::binary>> = string
757757
new_data = apply_replace(whole, replacement, head)
758758
[new_data | apply_list(whole, rest, pos + length, replacement, tail)]
759759
end
@@ -788,7 +788,7 @@ defmodule Regex do
788788
end
789789

790790
defp get_index(string, {pos, length}) do
791-
<<_::size(pos)-binary, res::size(length)-binary, _::binary>> = string
791+
<<_::size(^pos)-binary, res::size(^length)-binary, _::binary>> = string
792792
res
793793
end
794794

lib/elixir/lib/string.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ defmodule String do
673673
defp do_split_at(string, position) do
674674
remaining = byte_size_remaining_at(string, position)
675675
start = byte_size(string) - remaining
676-
<<left::size(start)-binary, right::size(remaining)-binary>> = string
676+
<<left::size(^start)-binary, right::size(^remaining)-binary>> = string
677677
{left, right}
678678
end
679679

@@ -1001,7 +1001,7 @@ defmodule String do
10011001
defp replace_leading(string, match, replacement, prefix_size, suffix_size, acc)
10021002
when suffix_size >= 0 do
10031003
case string do
1004-
<<prefix::size(prefix_size)-binary, suffix::binary>> when prefix == match ->
1004+
<<prefix::size(^prefix_size)-binary, suffix::binary>> when prefix == match ->
10051005
replace_leading(
10061006
suffix,
10071007
match,
@@ -1060,7 +1060,7 @@ defmodule String do
10601060
defp replace_trailing(string, match, replacement, prefix_size, suffix_size, acc)
10611061
when prefix_size >= 0 do
10621062
case string do
1063-
<<prefix::size(prefix_size)-binary, suffix::binary>> when suffix == match ->
1063+
<<prefix::size(^prefix_size)-binary, suffix::binary>> when suffix == match ->
10641064
replace_trailing(
10651065
prefix,
10661066
match,
@@ -1113,7 +1113,7 @@ defmodule String do
11131113
prefix_size = byte_size(match)
11141114

11151115
case string do
1116-
<<prefix::size(prefix_size)-binary, suffix::binary>> when prefix == match ->
1116+
<<prefix::size(^prefix_size)-binary, suffix::binary>> when prefix == match ->
11171117
prepend_unless_empty(replacement, suffix)
11181118

11191119
_ ->
@@ -1156,7 +1156,7 @@ defmodule String do
11561156
prefix_size = byte_size(string) - suffix_size
11571157

11581158
case string do
1159-
<<prefix::size(prefix_size)-binary, suffix::binary>> when suffix == match ->
1159+
<<prefix::size(^prefix_size)-binary, suffix::binary>> when suffix == match ->
11601160
append_unless_empty(prefix, replacement)
11611161

11621162
_ ->

lib/elixir/lib/string_io.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,13 @@ defmodule StringIO do
322322
end
323323

324324
defp get_chars(input, :latin1, count) do
325-
<<chars::binary-size(count), rest::binary>> = input
325+
<<chars::binary-size(^count), rest::binary>> = input
326326
{chars, rest}
327327
end
328328

329329
defp get_chars(input, :unicode, count) do
330330
with {:ok, count} <- split_at(input, count, 0) do
331-
<<chars::binary-size(count), rest::binary>> = input
331+
<<chars::binary-size(^count), rest::binary>> = input
332332
{chars, rest}
333333
end
334334
end
@@ -398,7 +398,7 @@ defmodule StringIO do
398398
defp get_until(chars, encoding, mod, fun, args, continuation, count) do
399399
case bytes_until_eol(chars, encoding, 0) do
400400
{kind, size} when kind in [:split, :replace_split] ->
401-
<<line::binary-size(size), rest::binary>> = chars
401+
<<line::binary-size(^size), rest::binary>> = chars
402402

403403
case apply(mod, fun, [continuation, binary_to_list(line, encoding) | args]) do
404404
{:done, result, :eof} ->

lib/elixir/src/elixir.hrl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
-record(elixir_ex, {
99
caller=false, %% stores if __CALLER__ is allowed
1010
%% TODO: Remove warn and everywhere it is set in v2.0
11-
prematch=warn, %% {Read, Counter} | warn | raise | pin | {bitsize,PreVars,OriginalVars}
11+
prematch=warn, %% {Read, Counter, {bitsize, Original} | none} | warn | raise | pin
1212
stacktrace=false, %% stores if __STACKTRACE__ is allowed
1313
unused={#{}, 0}, %% a map of unused vars and a version counter for vars
1414
vars={#{}, false} %% a tuple with maps of read and optional write current vars

lib/elixir/src/elixir_bitstring.erl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,11 @@ expand_spec_arg(Expr, S, _OriginalS, E) when is_atom(Expr); is_integer(Expr) ->
262262
{Expr, S, E};
263263
expand_spec_arg(Expr, S, OriginalS, #{context := match} = E) ->
264264
%% We can only access variables that are either on prematch or not in original
265-
#elixir_ex{prematch={PreRead, Counter}} = S,
265+
#elixir_ex{prematch={PreRead, PreCounter, _} = OldPre} = S,
266266
#elixir_ex{vars={OriginalRead, _}} = OriginalS,
267-
Prematch = {bitsize, PreRead, OriginalRead},
268-
{EExpr, SE, EE} = elixir_expand:expand(Expr, S#elixir_ex{prematch=Prematch}, E#{context := guard}),
269-
{EExpr, SE#elixir_ex{prematch={PreRead, Counter}}, EE#{context := match}};
267+
NewPre = {PreRead, PreCounter, {bitsize, OriginalRead}},
268+
{EExpr, SE, EE} = elixir_expand:expand(Expr, S#elixir_ex{prematch=NewPre}, E#{context := guard}),
269+
{EExpr, SE#elixir_ex{prematch=OldPre}, EE#{context := match}};
270270
expand_spec_arg(Expr, S, OriginalS, E) ->
271271
elixir_expand:expand(Expr, elixir_env:reset_read(S, OriginalS), E).
272272

lib/elixir/src/elixir_clauses.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ match(Fun, Expr, AfterS, BeforeS, E) ->
1414
#elixir_ex{vars={Read, _}, prematch=Prematch} = BeforeS,
1515

1616
CallS = BeforeS#elixir_ex{
17-
prematch={Read, Counter},
17+
prematch={Read, Counter, none},
1818
unused=Unused,
1919
vars=Current
2020
},
@@ -32,7 +32,7 @@ match(Fun, Expr, AfterS, BeforeS, E) ->
3232
{EExpr, EndS, EndE}.
3333

3434
def({Meta, Args, Guards, Body}, S, E) ->
35-
{EArgs, SA, EA} = elixir_expand:expand_args(Args, S#elixir_ex{prematch={#{}, 0}}, E#{context := match}),
35+
{EArgs, SA, EA} = elixir_expand:expand_args(Args, S#elixir_ex{prematch={#{}, 0, none}}, E#{context := match}),
3636
{EGuards, SG, EG} = guard(Guards, SA#elixir_ex{prematch=raise}, EA#{context := guard}),
3737
{EBody, SB, EB} = elixir_expand:expand(Body, elixir_env:set_prematch_from_config(SG), EG#{context := nil}),
3838
elixir_env:check_unused_vars(SB, EB),

0 commit comments

Comments
 (0)