Skip to content

Commit 334697a

Browse files
authored
Fix handling of small files and files with null in first 8 bytes (#116)
The `read -rn 8` command doesn't seem to cope with small files, and does all kinds of strange things (on macOS at least) including: - not reading anything at all from files with short first lines - reading too much from files with long first lines (more than 8 chars) Switch to us `head -c8` instead, which is safer, plus some fiddly use of `tr` to ignore null bytes early in a way that works for older and newer versions of bash.
1 parent 331b4af commit 334697a

File tree

3 files changed

+74
-1
lines changed

3 files changed

+74
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The format is based on [Keep a Changelog][1], and this project adheres to
2525
- Zsh completion. (#107)
2626
- Fix salt generation for partial (patch) commits (#118)
2727
- Improve command hint to fix secret files not encrypted in index (#120)
28+
- Fix handling of files with null in first 8 bytes (#116)
2829

2930
## [2.1.0] - 2020-09-07
3031

tests/test_crypt.bats

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,77 @@ function check_repo_is_clean {
139139
rm "$FILENAME"
140140
}
141141

142+
@test "crypt: handle very small file" {
143+
FILENAME="small file.txt"
144+
SECRET_CONTENT="sh"
145+
SECRET_CONTENT_ENC="U2FsdGVkX1/NlZCZ0ho/TL+5kTxm/R/X5nfATzQLKfI="
146+
147+
encrypt_named_file "$FILENAME" "$SECRET_CONTENT"
148+
[[ "${output}" = *"Encrypt file \"$FILENAME\""* ]]
149+
150+
# Working copy is decrypted
151+
run cat "$FILENAME"
152+
[ "$status" -eq 0 ]
153+
[ "${lines[0]}" = "$SECRET_CONTENT" ]
154+
155+
# Git internal copy is encrypted
156+
run git show HEAD:"$FILENAME" --no-textconv
157+
[ "$status" -eq 0 ]
158+
[ "${lines[0]}" = "$SECRET_CONTENT_ENC" ]
159+
160+
# transcrypt --show-raw shows encrypted content
161+
run ../transcrypt --show-raw "$FILENAME"
162+
[ "$status" -eq 0 ]
163+
[ "${lines[0]}" = "==> $FILENAME <==" ]
164+
[ "${lines[1]}" = "$SECRET_CONTENT_ENC" ]
165+
166+
# git ls-crypt lists encrypted file
167+
run git ls-crypt
168+
[ "$status" -eq 0 ]
169+
[ "${lines[0]}" = "$FILENAME" ]
170+
171+
# transcrypt --list lists encrypted file"
172+
run ../transcrypt --list
173+
[ "$status" -eq 0 ]
174+
[ "${lines[0]}" = "$FILENAME" ]
175+
176+
rm "$FILENAME"
177+
}
178+
179+
@test "crypt: handle file with problematic bytes" {
180+
FILENAME="problem bytes file.txt"
181+
SECRET_CONTENT_ENC="U2FsdGVkX1/RVkIfYCsbUMcvQlC2vWZJVQtZSuppd7Q="
182+
183+
# Write octal byte 375 and null byte as file contents
184+
printf "\375 \0 shh" > "$FILENAME"
185+
186+
encrypt_named_file "$FILENAME"
187+
[[ "${output}" = *"Encrypt file \"$FILENAME\""* ]]
188+
189+
# Git internal copy is encrypted
190+
run git show HEAD:"$FILENAME" --no-textconv
191+
[ "$status" -eq 0 ]
192+
[ "${lines[0]}" = "$SECRET_CONTENT_ENC" ]
193+
194+
# transcrypt --show-raw shows encrypted content
195+
run ../transcrypt --show-raw "$FILENAME"
196+
[ "$status" -eq 0 ]
197+
[ "${lines[0]}" = "==> $FILENAME <==" ]
198+
[ "${lines[1]}" = "$SECRET_CONTENT_ENC" ]
199+
200+
# git ls-crypt lists encrypted file
201+
run git ls-crypt
202+
[ "$status" -eq 0 ]
203+
[ "${lines[0]}" = "$FILENAME" ]
204+
205+
# transcrypt --list lists encrypted file"
206+
run ../transcrypt --list
207+
[ "$status" -eq 0 ]
208+
[ "${lines[0]}" = "$FILENAME" ]
209+
210+
rm "$FILENAME"
211+
}
212+
142213
@test "crypt: transcrypt --upgrade applies new merge driver" {
143214
VERSION=$(../transcrypt -v | awk '{print $2}')
144215

transcrypt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ git_clean() {
127127
trap 'rm -f "$tempfile"' EXIT
128128
tee "$tempfile" &>/dev/null
129129
# the first bytes of an encrypted file are always "Salted" in Base64
130-
read -rn 8 firstbytes <"$tempfile"
130+
# The `head + LC_ALL=C tr` command handles binary data in old and new Bash (#116)
131+
firstbytes=$(head -c8 "$tempfile" | LC_ALL=C tr -d '\0')
131132
if [[ $firstbytes == "U2FsdGVk" ]]; then
132133
cat "$tempfile"
133134
else

0 commit comments

Comments
 (0)