Ensure errors are handled or logged
if err != nil {
1// Copyright 2016 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package tar67import (8 "bytes"9 "fmt"10 "strconv"11 "strings"12 "time"13)1415// hasNUL reports whether the NUL character exists within s.16func hasNUL(s string) bool {17 return strings.Contains(s, "\x00")18}1920// isASCII reports whether the input is an ASCII C-style string.21func isASCII(s string) bool {22 for _, c := range s {23 if c >= 0x80 || c == 0x00 {24 return false25 }26 }27 return true28}2930// toASCII converts the input to an ASCII C-style string.31// This is a best effort conversion, so invalid characters are dropped.32func toASCII(s string) string {33 if isASCII(s) {34 return s35 }36 b := make([]byte, 0, len(s))37 for _, c := range s {38 if c < 0x80 && c != 0x00 {39 b = append(b, byte(c))40 }41 }42 return string(b)43}4445type parser struct {46 err error // Last error seen47}4849type formatter struct {50 err error // Last error seen51}5253// parseString parses bytes as a NUL-terminated C-style string.54// If a NUL byte is not found then the whole slice is returned as a string.55func (*parser) parseString(b []byte) string {56 if i := bytes.IndexByte(b, 0); i >= 0 {57 return string(b[:i])58 }59 return string(b)60}6162// formatString copies s into b, NUL-terminating if possible.63func (f *formatter) formatString(b []byte, s string) {64 if len(s) > len(b) {65 f.err = ErrFieldTooLong66 }67 copy(b, s)68 if len(s) < len(b) {69 b[len(s)] = 070 }7172 // Some buggy readers treat regular files with a trailing slash73 // in the V7 path field as a directory even though the full path74 // recorded elsewhere (e.g., via PAX record) contains no trailing slash.75 if len(s) > len(b) && b[len(b)-1] == '/' {76 n := len(strings.TrimRight(s[:len(b)-1], "/"))77 b[n] = 0 // Replace trailing slash with NUL terminator78 }79}8081// fitsInBase256 reports whether x can be encoded into n bytes using base-25682// encoding. Unlike octal encoding, base-256 encoding does not require that the83// string ends with a NUL character. Thus, all n bytes are available for output.84//85// If operating in binary mode, this assumes strict GNU binary mode; which means86// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is87// equivalent to the sign bit in two's complement form.88func fitsInBase256(n int, x int64) bool {89 binBits := uint(n-1) * 890 return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)91}9293// parseNumeric parses the input as being encoded in either base-256 or octal.94// This function may return negative numbers.95// If parsing fails or an integer overflow occurs, err will be set.96func (p *parser) parseNumeric(b []byte) int64 {97 // Check for base-256 (binary) format first.98 // If the first bit is set, then all following bits constitute a two's99 // complement encoded number in big-endian byte order.100 if len(b) > 0 && b[0]&0x80 != 0 {101 // Handling negative numbers relies on the following identity:102 // -a-1 == ^a103 //104 // If the number is negative, we use an inversion mask to invert the105 // data bytes and treat the value as an unsigned number.106 var inv byte // 0x00 if positive or zero, 0xff if negative107 if b[0]&0x40 != 0 {108 inv = 0xff109 }110111 var x uint64112 for i, c := range b {113 c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing114 if i == 0 {115 c &= 0x7f // Ignore signal bit in first byte116 }117 if (x >> 56) > 0 {118 p.err = ErrHeader // Integer overflow119 return 0120 }121 x = x<<8 | uint64(c)122 }123 if (x >> 63) > 0 {124 p.err = ErrHeader // Integer overflow125 return 0126 }127 if inv == 0xff {128 return ^int64(x)129 }130 return int64(x)131 }132133 // Normal case is base-8 (octal) format.134 return p.parseOctal(b)135}136137// formatNumeric encodes x into b using base-8 (octal) encoding if possible.138// Otherwise it will attempt to use base-256 (binary) encoding.139func (f *formatter) formatNumeric(b []byte, x int64) {140 if fitsInOctal(len(b), x) {141 f.formatOctal(b, x)142 return143 }144145 if fitsInBase256(len(b), x) {146 for i := len(b) - 1; i >= 0; i-- {147 b[i] = byte(x)148 x >>= 8149 }150 b[0] |= 0x80 // Highest bit indicates binary format151 return152 }153154 f.formatOctal(b, 0) // Last resort, just write zero155 f.err = ErrFieldTooLong156}157158func (p *parser) parseOctal(b []byte) int64 {159 // Because unused fields are filled with NULs, we need160 // to skip leading NULs. Fields may also be padded with161 // spaces or NULs.162 // So we remove leading and trailing NULs and spaces to163 // be sure.164 b = bytes.Trim(b, " \x00")165166 if len(b) == 0 {167 return 0168 }169 x, perr := strconv.ParseUint(p.parseString(b), 8, 64)170 if perr != nil {171 p.err = ErrHeader172 }173 return int64(x)174}175176func (f *formatter) formatOctal(b []byte, x int64) {177 if !fitsInOctal(len(b), x) {178 x = 0 // Last resort, just write zero179 f.err = ErrFieldTooLong180 }181182 s := strconv.FormatInt(x, 8)183 // Add leading zeros, but leave room for a NUL.184 if n := len(b) - len(s) - 1; n > 0 {185 s = strings.Repeat("0", n) + s186 }187 f.formatString(b, s)188}189190// fitsInOctal reports whether the integer x fits in a field n-bytes long191// using octal encoding with the appropriate NUL terminator.192func fitsInOctal(n int, x int64) bool {193 octBits := uint(n-1) * 3194 return x >= 0 && (n >= 22 || x < 1<<octBits)195}196197// parsePAXTime takes a string of the form %d.%d as described in the PAX198// specification. Note that this implementation allows for negative timestamps,199// which is allowed for by the PAX specification, but not always portable.200func parsePAXTime(s string) (time.Time, error) {201 const maxNanoSecondDigits = 9202203 // Split string into seconds and sub-seconds parts.204 ss, sn, _ := strings.Cut(s, ".")205206 // Parse the seconds.207 secs, err := strconv.ParseInt(ss, 10, 64)208 if err != nil {209 return time.Time{}, ErrHeader210 }211 if len(sn) == 0 {212 return time.Unix(secs, 0), nil // No sub-second values213 }214215 // Parse the nanoseconds.216 // Initialize an array with '0's to handle right padding automatically.217 nanoDigits := [maxNanoSecondDigits]byte{'0', '0', '0', '0', '0', '0', '0', '0', '0'}218 for i := range len(sn) {219 switch c := sn[i]; {220 case c < '0' || c > '9':221 return time.Time{}, ErrHeader222 case i < len(nanoDigits):223 nanoDigits[i] = c224 }225 }226 nsecs, _ := strconv.ParseInt(string(nanoDigits[:]), 10, 64) // Must succeed after validation227 if len(ss) > 0 && ss[0] == '-' {228 return time.Unix(secs, -1*nsecs), nil // Negative correction229 }230 return time.Unix(secs, nsecs), nil231}232233// formatPAXTime converts ts into a time of the form %d.%d as described in the234// PAX specification. This function is capable of negative timestamps.235func formatPAXTime(ts time.Time) (s string) {236 secs, nsecs := ts.Unix(), ts.Nanosecond()237 if nsecs == 0 {238 return strconv.FormatInt(secs, 10)239 }240241 // If seconds is negative, then perform correction.242 sign := ""243 if secs < 0 {244 sign = "-" // Remember sign245 secs = -(secs + 1) // Add a second to secs246 nsecs = -(nsecs - 1e9) // Take that second away from nsecs247 }248 return strings.TrimRight(fmt.Sprintf("%s%d.%09d", sign, secs, nsecs), "0")249}250251// parsePAXRecord parses the input PAX record string into a key-value pair.252// If parsing is successful, it will slice off the currently read record and253// return the remainder as r.254func parsePAXRecord(s string) (k, v, r string, err error) {255 // The size field ends at the first space.256 nStr, rest, ok := strings.Cut(s, " ")257 if !ok {258 return "", "", s, ErrHeader259 }260261 // Parse the first token as a decimal integer.262 n, perr := strconv.ParseInt(nStr, 10, 0) // Intentionally parse as native int263 if perr != nil || n < 5 || n > int64(len(s)) {264 return "", "", s, ErrHeader265 }266 n -= int64(len(nStr) + 1) // convert from index in s to index in rest267 if n <= 0 {268 return "", "", s, ErrHeader269 }270271 // Extract everything between the space and the final newline.272 rec, nl, rem := rest[:n-1], rest[n-1:n], rest[n:]273 if nl != "\n" {274 return "", "", s, ErrHeader275 }276277 // The first equals separates the key from the value.278 k, v, ok = strings.Cut(rec, "=")279 if !ok {280 return "", "", s, ErrHeader281 }282283 if !validPAXRecord(k, v) {284 return "", "", s, ErrHeader285 }286 return k, v, rem, nil287}288289// formatPAXRecord formats a single PAX record, prefixing it with the290// appropriate length.291func formatPAXRecord(k, v string) (string, error) {292 if !validPAXRecord(k, v) {293 return "", ErrHeader294 }295296 const padding = 3 // Extra padding for ' ', '=', and '\n'297 size := len(k) + len(v) + padding298 size += len(strconv.Itoa(size))299 record := strconv.Itoa(size) + " " + k + "=" + v + "\n"300301 // Final adjustment if adding size field increased the record size.302 if len(record) != size {303 size = len(record)304 record = strconv.Itoa(size) + " " + k + "=" + v + "\n"305 }306 return record, nil307}308309// validPAXRecord reports whether the key-value pair is valid where each310// record is formatted as:311//312// "%d %s=%s\n" % (size, key, value)313//314// Keys and values should be UTF-8, but the number of bad writers out there315// forces us to be more liberal.316// Thus, we only reject all keys with NUL, and only reject NULs in values317// for the PAX version of the USTAR string fields.318// The key must not contain an '=' character.319func validPAXRecord(k, v string) bool {320 if k == "" || strings.Contains(k, "=") {321 return false322 }323 switch k {324 case paxPath, paxLinkpath, paxUname, paxGname:325 return !hasNUL(v)326 default:327 return !hasNUL(k)328 }329}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.