From 310ba828289f8c4924bc0f319b72e151f5f079f7 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 9 Aug 2017 11:08:55 -0700 Subject: [PATCH] archive/tar: ensure input fits in octal field The prior logic would over-write the NUL-terminator if the octal value was long enough. In order to prevent this, we add a fitsInOctal function that does the proper check. The relevant USTAR specification about NUL-terminator is: <<< Each numeric field is terminated by one or more or NUL characters. >>> Change-Id: I6fbc6e8fe71168727eea201925d0fe08d43116ac Reviewed-on: https://go-review.googlesource.com/54432 Reviewed-by: Ian Lance Taylor --- src/archive/tar/strconv.go | 15 ++++++++- src/archive/tar/strconv_test.go | 58 +++++++++++++++++++++++++++++++++ src/archive/tar/writer.go | 25 ++++++-------- 3 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/archive/tar/strconv.go b/src/archive/tar/strconv.go index 3a635834ff..7629c43c65 100644 --- a/src/archive/tar/strconv.go +++ b/src/archive/tar/strconv.go @@ -124,8 +124,14 @@ func (p *parser) parseNumeric(b []byte) int64 { return p.parseOctal(b) } -// Write x into b, as binary (GNUtar/star extension). +// formatNumeric encodes x into b using base-8 (octal) encoding if possible. +// Otherwise it will attempt to use base-256 (binary) encoding. func (f *formatter) formatNumeric(b []byte, x int64) { + if fitsInOctal(len(b), x) { + f.formatOctal(b, x) + return + } + if fitsInBase256(len(b), x) { for i := len(b) - 1; i >= 0; i-- { b[i] = byte(x) @@ -166,6 +172,13 @@ func (f *formatter) formatOctal(b []byte, x int64) { f.formatString(b, s) } +// fitsInOctal reports whether the integer x fits in a field n-bytes long +// using octal encoding with the appropriate NUL terminator. +func fitsInOctal(n int, x int64) bool { + octBits := uint(n-1) * 3 + return x >= 0 && (n >= 22 || x < 1<