Skip to content

Commit 69cb8b9

Browse files
committed
Fix binary encoding for parser translator
Skipping detecting the encoding is almost always right, just for binary it should actually happen. A symbol containing escapes that are invalid in utf-8 would fail to parse since symbols must be valid in the script encoding. Additionally, the parser gem would raise an exception somewhere during string handling
1 parent cba57f0 commit 69cb8b9

File tree

8 files changed

+109
-3
lines changed

8 files changed

+109
-3
lines changed

lib/prism/translation/parser.rb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def parse(source_buffer)
5151
source = source_buffer.source
5252

5353
offset_cache = build_offset_cache(source)
54-
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache)
54+
result = unwrap(Prism.parse(source, **prism_options), offset_cache)
5555

5656
build_ast(result.value, offset_cache)
5757
ensure
@@ -64,7 +64,7 @@ def parse_with_comments(source_buffer)
6464
source = source_buffer.source
6565

6666
offset_cache = build_offset_cache(source)
67-
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache)
67+
result = unwrap(Prism.parse(source, **prism_options), offset_cache)
6868

6969
[
7070
build_ast(result.value, offset_cache),
@@ -83,7 +83,7 @@ def tokenize(source_buffer, recover = false)
8383
offset_cache = build_offset_cache(source)
8484
result =
8585
begin
86-
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache)
86+
unwrap(Prism.parse_lex(source, **prism_options), offset_cache)
8787
rescue ::Parser::SyntaxError
8888
raise if !recover
8989
end
@@ -285,6 +285,20 @@ def build_range(location, offset_cache)
285285
)
286286
end
287287

288+
# Options for how prism should parse/lex the source.
289+
def prism_options
290+
options = {
291+
filepath: @source_buffer.name,
292+
version: convert_for_prism(version),
293+
partial_script: true,
294+
}
295+
# The parser gem always encodes to UTF-8, unless it is binary.
296+
# https://github.com/whitequark/parser/blob/v3.3.6.0/lib/parser/source/buffer.rb#L80-L107
297+
options[:encoding] = false if @source_buffer.source.encoding != Encoding::BINARY
298+
299+
options
300+
end
301+
288302
# Converts the version format handled by Parser to the format handled by Prism.
289303
def convert_for_prism(version)
290304
case version
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# encoding: binary
2+
3+
"\xcd"
4+
5+
:"\xcd"
6+
7+
/#{"\xcd"}/
8+
9+
%W[\xC0]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# encoding: euc-jp
2+
3+
# \x8E indicates a double-byte character, \x01 is not a valid second byte in euc-jp
4+
"\x8E\x01"
5+
6+
%W["\x8E\x01"]

test/prism/ruby/parser_test.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ class ParserTest < TestCase
9797
"dash_heredocs.txt",
9898
"dos_endings.txt",
9999
"embdoc_no_newline_at_end.txt",
100+
"encoding_binary.txt",
101+
"encoding_euc_jp.txt",
100102
"heredoc_with_comment.txt",
101103
"heredocs_with_ignored_newlines.txt",
102104
"indented_file_end.txt",

test/prism/ruby/ruby_parser_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def ==(other)
2626
module Prism
2727
class RubyParserTest < TestCase
2828
todos = [
29+
"encoding_euc_jp.txt",
2930
"newline_terminated.txt",
3031
"regex_char_width.txt",
3132
"seattlerb/bug169.txt",

test/prism/snapshots/encoding_binary.txt

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snapshots/encoding_euc_jp.txt

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/prism/snippets_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
module Prism
66
class SnippetsTest < TestCase
77
except = [
8+
"encoding_binary.txt",
89
"newline_terminated.txt",
910
"seattlerb/begin_rescue_else_ensure_no_bodies.txt",
1011
"seattlerb/case_in.txt",

0 commit comments

Comments
 (0)