-
Notifications
You must be signed in to change notification settings - Fork 895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GODRIVER-3240 Code hardening. #1684
Conversation
API Change ReportNo changes found! |
bson/bsonrw/extjson_wrappers.go
Outdated
i, err := strconv.ParseUint(val.v.(string), 16, 64) | ||
if err != nil { | ||
return nil, 0, fmt.Errorf("invalid $binary subType string: %s", val.v.(string)) | ||
} | ||
|
||
subType = byte(i) | ||
b := []byte{0, 0, 0, 0, 0, 0, 0, 0} | ||
binary.LittleEndian.PutUint64(b, i) | ||
subType = b[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use ParseUint
to limit the range of the parsed subtype value by using bitSize=8
. I also recommend adding the parse error to returned error.
E.g.
i, err := strconv.ParseUint(val.v.(string), 16, 8)
if err != nil {
return nil, 0, fmt.Errorf("invalid $binary subType string %q: %w", val.v.(string), err)
}
subType = byte(i)
4626635
to
27f5ac7
Compare
c34137f
to
dfd8a33
Compare
dfd8a33
to
0fb85cf
Compare
bson/bsonrw/extjson_wrappers.go
Outdated
b := []byte{0, 0, 0, 0, 0, 0, 0, 0} | ||
binary.LittleEndian.PutUint64(b, i) | ||
subType = b[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we already apply the bounds check in the ParseUint
call, it should be safe to assume that i
is in the range [0, 255]
. In that case, we can keep the existing uint64
-> byte
conversion.
b := []byte{0, 0, 0, 0, 0, 0, 0, 0} | |
binary.LittleEndian.PutUint64(b, i) | |
subType = b[0] | |
subType = byte(i) |
mongo/options/clientoptions.go
Outdated
dataSize := len(keyData) | ||
certSize := len(certData) | ||
if math.MaxInt-dataSize < certSize { | ||
return "", errors.New("size overflow") | ||
} | ||
dataSize += certSize | ||
if math.MaxInt-dataSize < 1 { | ||
return "", errors.New("size overflow") | ||
} | ||
dataSize++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can simplify the logic here by adding some additional data size validation. AFAIK there's no case where an X.509 key and cert should be anywhere near 64MiB, so we can avoid the integer overflow and check for reasonable data size at the same time.
dataSize := len(keyData) | |
certSize := len(certData) | |
if math.MaxInt-dataSize < certSize { | |
return "", errors.New("size overflow") | |
} | |
dataSize += certSize | |
if math.MaxInt-dataSize < 1 { | |
return "", errors.New("size overflow") | |
} | |
dataSize++ | |
keySize := len(keyData) | |
if keySize > 64*1024*1024 { | |
return "", errors.New("X.509 key must be less than 64 MiB") | |
} | |
certSize := len(certData) | |
if certSize > 64*1024*1024 { | |
return "", errors.New("X.509 certificate must be less than 64 MiB") | |
} | |
data := make([]byte, 0, keySize+certSize+1) |
@@ -164,11 +164,15 @@ func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t refl | |||
|
|||
return reflect.ValueOf(uint64(i64)), nil | |||
case reflect.Uint: | |||
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint | |||
if i64 < 0 { | |||
return emptyValue, fmt.Errorf("%d overflows uint", i64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a more accurate error message.
return emptyValue, fmt.Errorf("%d overflows uint", i64) | |
return emptyValue, fmt.Errorf("%d underflows uint", i64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems better to keep the error message consistent with other unsigned types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable. We can fix them all at the same time. Consider this comment resolved.
return "", errors.New("X.509 certificate must be less than 64 MiB") | ||
} | ||
dataSize := keySize + certSize + 1 | ||
if dataSize > math.MaxInt { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An additional fail-safe check.
The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! 👍
GODRIVER-3240
Summary
Background & Motivation