Skip to content

Commit 753013b

Browse files
committed
refactor: Use '-N1' for reading characters from input
This prevents a lot of the truncating and mangling errors that were previously occuring. This feature was added in Bash 4.1
1 parent 79bbcf5 commit 753013b

File tree

8 files changed

+115
-56
lines changed

8 files changed

+115
-56
lines changed

pkg/lib/commands/parse.sh

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ bash_toml.do_parse() {
99
declare -i PARSER_LINE_NUMBER=1
1010
declare -i PARSER_COLUMN_NUMBER=0
1111

12-
while IFS= read -rn 1 char; do
12+
while IFS= read -rN1 char; do
1313
if bash_toml.is.newline "$char"; then
1414
PARSER_COLUMN_NUMBER=0
1515
PARSER_LINE_NUMBER+=1
@@ -55,16 +55,14 @@ bash_toml.do_parse() {
5555
MODE_ANY_BEFORE_VALUE)
5656
if bash_toml.is.whitespace "$char"; then
5757
:
58-
elif bash_toml.is.newline "$char"; then
59-
# TODO: not being fired?
60-
bash_toml.parse_fail 'KEY_ABSENT' "Key name found without value 2"
61-
return 1
6258
elif bash_toml.is.double_quote "$char"; then
6359
mode='MODE_DOUBLEQUOTE_DURING_VALUE'
6460
bash_toml.init_value_string
6561
elif bash_toml.is.single_quote "$char"; then
6662
mode='MODE_SINGLEQUOTE_DURING_VALUE'
6763
bash_toml.init_value_string
64+
elif bash_toml.is.newline "$char"; then
65+
bash_toml.parse_fail 'UNEXPECTED_NEWLINE' 'Expected to find value on the same line'
6866
elif bash_toml.is.empty "$char"; then
6967
bash_toml.parse_fail 'UNEXPECTED_EOF' 'Expected to find value on the same line'
7068
return 1
@@ -120,15 +118,15 @@ bash_toml.do_parse() {
120118
# directly after the `"`
121119
MODE_DOUBLEQUOTE_DURING_VALUE)
122120
if bash_toml.is.double_quote "$char"; then
123-
mode='MODE_ANY_AFTER_VALUE'
121+
mode='MODE_DEFAULT_END'
124122
elif bash_toml.is.backslash "$char"; then
125123
mode='MODE_DOUBLEQUOTE_DURING_ESCAPE_SEQUENCE'
124+
elif bash_toml.is.newline "$char"; then
125+
bash_toml.parse_fail 'UNEXPECTED_NEWLINE' "Literal newlines must not be present in double quotes"
126+
return 1
126127
elif bash_toml.is.control_character "$char"; then
127128
# TODO: this code path won't get activated
128129
:
129-
elif bash_toml.is.empty "$char"; then
130-
bash_toml.parse_fail 'UNEXPECTED_EOF' "Must complete the basic string with a double quote"
131-
return 1
132130
else
133131
bash_toml.append_value_string "$char"
134132
fi
@@ -224,9 +222,9 @@ bash_toml.do_parse() {
224222
# directly after the `'`
225223
MODE_SINGLEQUOTE_DURING_VALUE)
226224
if bash_toml.is.single_quote "$char"; then
227-
mode='MODE_ANY_AFTER_VALUE'
225+
mode='MODE_DEFAULT_END'
228226
elif bash_toml.is.newline "$char"; then
229-
bash_toml.parse_fail 'VALUE_STRING_INVALID' "Newlines are not valid in single quote"
227+
bash_toml.parse_fail 'UNEXPECTED_NEWLINE' "Newlines are not valid in single quote"
230228
return 1
231229
elif bash_toml.is.empty "$char"; then
232230
bash_toml.parse_fail 'UNEXPECTED_EOF' "Must complete the literal string with a single quote"
@@ -235,7 +233,7 @@ bash_toml.do_parse() {
235233
bash_toml.append_value_string "$char"
236234
fi
237235
;;
238-
MODE_ANY_AFTER_VALUE)
236+
MODE_DEFAULT_END)
239237
if bash_toml.is.whitespace "$char"; then
240238
:
241239
elif bash_toml.is.newline "$char"; then
@@ -252,6 +250,14 @@ bash_toml.do_parse() {
252250
esac
253251
done
254252

253+
case "$mode" in
254+
MODE_DEFAULT|MODE_DEFAULT_END)
255+
;;
256+
*)
257+
bash_toml.parse_fail 'UNEXPECTED_EOF' 'Did not finish parsing construct'
258+
return 1
259+
;;
260+
esac
255261
# If we try to set an empty key with a value, then later on,
256262
# we can access any value (using a non-integer key), and we
257263
# will get a result that equals the original value value

pkg/lib/util/util.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ declare -gA BASH_TOML_ERRORS=(
77
[UNICODE_INVALID]='The resulting unicode code point was invalid'
88
[KEY_ABSENT]='Key does not have a value'
99
[UNEXPECTED_EOF]='Unexpected end of line'
10+
[UNEXPECTED_NEWLINE]='Unexpected newline'
1011
[UNEXPECTED_CHARACTER]='An unexpected character was encountered' # Generalization of any of the following errors
1112
[KEY_INVALID]='The key is not valid'
1213
[VALUE_INVALID]='The value could not be parsed'

tests/key-bare.bats

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,48 @@
22

33
load './util/init.sh'
44

5-
@test "fails on invalid bare key" {
6-
run bash_toml.do_parse <<-"EOF"
7-
fox
8-
EOF
5+
@test "fails on invalid bare key 1" {
6+
run bash_toml.do_parse < <(printf 'fox')
97

108
assert_failure
11-
assert_output -p 'KEY_INVALID'
9+
assert_output -p 'UNEXPECTED_EOF'
1210
}
1311

1412
@test "fails on invalid bare key 2" {
15-
run bash_toml.do_parse <<-"EOF"
16-
f ox
17-
EOF
13+
run bash_toml.do_parse < <(printf 'fox\n')
1814

1915
assert_failure
2016
assert_output -p 'KEY_INVALID'
2117
}
2218

2319
@test "fails on invalid bare key 3" {
24-
run bash_toml.do_parse <<-"EOF"
25-
f!ox
26-
EOF
20+
run bash_toml.do_parse < <(printf 'f ox')
2721

2822
assert_failure
29-
assert_output -p 'UNEXPECTED_CHARACTER'
23+
assert_output -p 'KEY_INVALID'
3024
}
3125

3226
@test "fails on invalid bare key 4" {
33-
run bash_toml.do_parse <<-"EOF"
34-
fox=
35-
EOF
27+
run bash_toml.do_parse < <(printf 'f!ox')
28+
29+
assert_failure
30+
assert_output -p 'UNEXPECTED_CHARACTER'
31+
}
32+
33+
@test "fails on invalid bare key 5" {
34+
run bash_toml.do_parse < <(printf 'fox=')
3635

3736
assert_failure
3837
assert_output -p 'UNEXPECTED_EOF'
3938
}
4039

40+
@test "fails on invalid bare key 6" {
41+
run bash_toml.do_parse < <(printf 'fox=\n')
42+
43+
assert_failure
44+
assert_output -p 'UNEXPECTED_NEWLINE'
45+
}
46+
4147
@test "succeeds on valid bare key 1" {
4248
bash_toml.do_parse <<-"EOF"
4349
fox = 'value'

tests/key-quoted.bats

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,75 @@
22

33
load './util/init.sh'
44

5-
@test "fails on invalid quoted key" {
6-
run bash_toml.do_parse <<< '"'
5+
@test "fails on invalid quoted key 1" {
6+
run bash_toml.do_parse < <(printf '"')
77

88
assert_failure
9-
assert_output -p 'KEY_INVALID'
9+
assert_output -p 'UNEXPECTED_EOF'
1010
}
1111

1212
@test "fails on invalid quoted key 2" {
13-
run bash_toml.do_parse <<< $'"\n'
13+
run bash_toml.do_parse < <(printf '"\n')
1414

1515
assert_failure
1616
assert_output -p 'KEY_INVALID'
1717
}
1818

1919
@test "fails on invalid quoted key 3" {
20-
run bash_toml.do_parse <<< '""'
20+
run bash_toml.do_parse < <(printf '""')
2121

2222
assert_failure
2323
assert_output -p 'UNEXPECTED_EOF'
2424
}
2525

2626
@test "fails on invalid quoted key 4" {
27-
run bash_toml.do_parse <<< '""='
27+
run bash_toml.do_parse < <(printf '""\n')
2828

2929
assert_failure
30-
assert_output -p 'UNEXPECTED_EOF'
30+
assert_output -p 'KEY_INVALID'
3131
}
3232

3333
@test "fails on invalid quoted key 5" {
34-
run bash_toml.do_parse <<< '"" ='
34+
run bash_toml.do_parse < <(printf '""=')
3535

3636
assert_failure
3737
assert_output -p 'UNEXPECTED_EOF'
3838
}
3939

4040
@test "fails on invalid quoted key 6" {
41-
run bash_toml.do_parse <<< \"\"\ =\'
41+
run bash_toml.do_parse < <(printf '""=\n')
42+
43+
assert_failure
44+
assert_output -p 'UNEXPECTED_NEWLINE'
45+
}
46+
47+
@test "fails on invalid quoted key 7" {
48+
run bash_toml.do_parse < <(printf '"" =')
4249

4350
assert_failure
4451
assert_output -p 'UNEXPECTED_EOF'
4552
}
4653

54+
@test "fails on invalid quoted key 8" {
55+
run bash_toml.do_parse < <(printf '"" =\n')
56+
57+
assert_failure
58+
assert_output -p 'UNEXPECTED_NEWLINE'
59+
}
60+
4761
@test "succeeds on valid quoted key 1" {
4862
bash_toml.do_parse <<-"EOF"
49-
"" = 'UwU'
63+
"" = ''
5064
EOF
5165
}
5266

5367
@test "succeeds on valid quoted key 2" {
68+
bash_toml.do_parse <<-"EOF"
69+
"" = 'UwU'
70+
EOF
71+
}
72+
73+
@test "succeeds on valid quoted key 3" {
5474
bash_toml.do_parse <<-"EOF"
5575
"fox" = 'UwU'
5676
EOF
@@ -59,7 +79,7 @@ load './util/init.sh'
5979
assert test_util.toml.key_has_value 'fox' 'UwU'
6080
}
6181

62-
@test "succeeds on valid quoted key 3" {
82+
@test "succeeds on valid quoted key 4" {
6383
bash_toml.do_parse <<-"EOF"
6484
"123" = 'UwU'
6585
EOF

tests/string-basic.bats

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,55 @@
33
load './util/init.sh'
44

55
@test "fails on invalid basic string 1" {
6-
run bash_toml.do_parse <<-"EOF"
7-
fox = "
8-
EOF
6+
run bash_toml.do_parse < <(printf 'fox = "')
97

108
assert_failure
119
assert_output -p "UNEXPECTED_EOF"
1210
}
1311

1412
@test "fails on invalid basic string 2" {
15-
run bash_toml.do_parse <<-"EOF"
16-
fox = "a
17-
EOF
13+
run bash_toml.do_parse < <(printf 'fox = "\n')
1814

1915
assert_failure
20-
assert_output -p "UNEXPECTED_EOF"
16+
assert_output -p "UNEXPECTED_NEWLINE"
2117
}
2218

23-
# TODO: this shouldn't be
2419
@test "fails on invalid basic string 3" {
25-
run bash_toml.do_parse <<< 'fox = "ab'
20+
run bash_toml.do_parse < <(printf 'fox = "a')
2621

2722
assert_failure
2823
assert_output -p "UNEXPECTED_EOF"
2924
}
3025

3126
@test "fails on invalid basic string 4" {
27+
run bash_toml.do_parse < <(printf 'fox = "a\n')
28+
29+
assert_failure
30+
assert_output -p "UNEXPECTED_NEWLINE"
31+
}
32+
33+
@test "fails on invalid basic string 5" {
34+
run bash_toml.do_parse < <(printf 'fox = "ab')
35+
36+
assert_failure
37+
assert_output -p "UNEXPECTED_EOF"
38+
}
39+
40+
@test "fails on invalid basic string 6" {
41+
run bash_toml.do_parse < <(printf 'fox = "ab\n')
42+
43+
assert_failure
44+
assert_output -p "UNEXPECTED_NEWLINE"
45+
}
46+
47+
@test "fails on invalid basic string 7" {
3248
run bash_toml.do_parse <<< 'fox = "\j"'
3349

3450
assert_failure
3551
assert_output -p "UNEXPECTED_CHARACTER"
3652
}
3753

38-
@test "fails on invalid basic string 5" {
54+
@test "fails on invalid basic string 8" {
3955
for hex in D800 DFFF; do
4056
run bash_toml.do_parse <<< "fox = "\"\\u"$hex"\"
4157

@@ -44,7 +60,7 @@ load './util/init.sh'
4460
done
4561
}
4662

47-
@test "fails on invalid basic string 6" {
63+
@test "fails on invalid basic string 9" {
4864
run bash_toml.do_parse <<-"EOF"
4965
fox = "\U00110000"
5066
EOF

tests/string-literal.bats

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
load './util/init.sh'
22

33
@test "fails on invalid literal string 1" {
4-
run bash_toml.do_parse <<-"EOF"
5-
fox = '
6-
EOF
4+
run bash_toml.do_parse < <(printf "fox = '")
75

86
assert_failure
97
assert_output -p "UNEXPECTED_EOF"
108
}
119

1210
@test "fails on invalid literal string 2" {
13-
run bash_toml.do_parse <<-"EOF"
14-
fox = 'a
15-
EOF
11+
run bash_toml.do_parse < <(printf "fox = '\n")
1612

1713
assert_failure
18-
assert_output -p "UNEXPECTED_EOF"
14+
assert_output -p "UNEXPECTED_NEWLINE"
1915
}
2016

2117
@test "fails on invalid literal string 3" {
18+
run bash_toml.do_parse < <(printf "fox = 'a")
19+
20+
assert_failure
21+
assert_output -p "UNEXPECTED_EOF"
22+
}
23+
24+
@test "fails on invalid literal string 4" {
25+
run bash_toml.do_parse < <(printf "fox = 'a\n")
26+
27+
assert_failure
28+
assert_output -p "UNEXPECTED_NEWLINE"
29+
}
30+
31+
@test "fails on invalid literal string 5" {
2232
run bash_toml.do_parse <<-"EOF"
2333
fox = '''
2434
EOF

tests/string-multiline-basic.bats

Whitespace-only changes.

tests/string-multiline-literal.bats

Whitespace-only changes.

0 commit comments

Comments
 (0)