Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 37 additions & 20 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
package utils

import (
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"math"
"net"
"os"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"

Expand All @@ -30,11 +31,9 @@
// All rights reserved.

var (
uuidSeed [24]byte
uuidCounter uint64
uuidSetup sync.Once
unitsSlice = []byte("kmgtp")
sizeMultipliers = [...]float64{1e3, 1e6, 1e9, 1e12, 1e15}
uuidSeed [24]byte
uuidCounter uint64
uuidSetup sync.Once
)

// UUID generates an universally unique identifier (UUID)
Expand Down Expand Up @@ -120,36 +119,54 @@
if strLen == 0 {
return 0
}

var unitPrefixPos, lastNumberPos int
// loop the string
// loop backwards to find the last numeric character and the unit prefix
for i := strLen - 1; i >= 0; i-- {
// check if the char is a number
c := humanReadableString[i]
if c >= '0' && c <= '9' {
lastNumberPos = i
break
} else if c != ' ' {
}
if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
unitPrefixPos = i
}
}

// fetch the number part and parse it to float
size, err := strconv.ParseFloat(humanReadableString[:lastNumberPos+1], 64)
if err != nil {
return 0
numPart := humanReadableString[:lastNumberPos+1]
var size float64
if strings.IndexByte(numPart, '.') >= 0 {
var err error
size, err = strconv.ParseFloat(numPart, 64)
if err != nil {
return 0
}
} else {
i64, err := strconv.ParseUint(numPart, 10, 64)
if err != nil {
return 0
}
size = float64(i64)
}

// check the multiplier from the string and use it
if unitPrefixPos > 0 {
// convert multiplier char to lowercase and check if exists in units slice
index := bytes.IndexByte(unitsSlice, toLowerTable[humanReadableString[unitPrefixPos]])
if index != -1 {
size *= sizeMultipliers[index]
switch humanReadableString[unitPrefixPos] {
case 'k', 'K':
size *= 1e3
case 'm', 'M':
size *= 1e6
case 'g', 'G':
size *= 1e9
case 't', 'T':
size *= 1e12
case 'p', 'P':
size *= 1e15
}
}

if size > float64(^uint(0)>>1) {
return int(^uint(0) >> 1)
if size > float64(math.MaxInt) {
return math.MaxInt

Check warning on line 168 in common.go

View check run for this annotation

Codecov / codecov/patch

common.go#L168

Added line #L168 was not covered by tests
}

return int(size)

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types High

Incorrect conversion of an unsigned 64-bit integer from
strconv.ParseUint
to a lower bit size type int without an upper bound check.
}
1 change: 1 addition & 0 deletions common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func Test_ConvertToBytes(t *testing.T) {
require.Equal(t, 0, ConvertToBytes("MB"))
require.Equal(t, 0, ConvertToBytes("invalidunit"))
require.Equal(t, 42, ConvertToBytes("42X")) // invalid unit
require.Equal(t, 123, ConvertToBytes("123a k")) // invalid unit
require.Equal(t, 0, ConvertToBytes("42.5.5MB")) // invalid format

// Test decimal numbers with various units
Expand Down
Loading