maltzsama opened a new issue, #176:
URL: https://github.com/apache/arrow-swift/issues/176
### Describe the bug, including details regarding any error messages,
version, and platform.
### Description
`ArrowReader.fromFile()` crashes with a fatal error when processing files
smaller than the Arrow file marker size (6 bytes), instead of returning a
`.failure` result.
### Root Cause
The `validateFileData()` function in `ArrowReaderHelper.swift` attempts to
read the first and last 6 bytes of the input data without first checking if the
data is large enough:
```swift
func validateFileData(_ data: Data) -> Bool {
let markerLength = FILEMARKER.utf8.count
let startString = String(decoding: data[..<markerLength], as: UTF8.self)
let endString = String(decoding: data[(data.count - markerLength)...],
as: UTF8.self)
return startString == FILEMARKER && endString == FILEMARKER
}
```
When `data.count < markerLength` (6 bytes), the subscript operations
`data[..<6]` and `data[(data.count - 6)...]` fail with a range error, causing a
crash instead of gracefully returning `false`.
### Impact
Any application using `ArrowReader.fromFile()` with user-supplied files can
be crashed by providing a file smaller than 12 bytes (or any non-Arrow file
that happens to be truncated). This is a denial of service vulnerability for
any application that doesn't perform pre-validation on file size.
### Expected Behavior
`ArrowReader.fromFile()` should gracefully handle files of any size and
return a `.failure` result with an appropriate `ArrowError` when the file is
not a valid Arrow file.
### Steps to Reproduce
```swift
let reader = ArrowReader()
let emptyFile = URL(fileURLWithPath: "/tmp/empty.bin")
try Data().write(to: emptyFile)
let result = reader.fromFile(emptyFile) // Crashes instead of returning
.failure
```
### Suggested Fix
Add a bounds check before accessing the data:
```swift
func validateFileData(_ data: Data) -> Bool {
let markerLength = FILEMARKER.utf8.count
guard data.count >= markerLength * 2 else { return false }
let startString = String(decoding: data.prefix(markerLength), as:
UTF8.self)
let endString = String(decoding: data.suffix(markerLength), as:
UTF8.self)
return startString == FILEMARKER && endString == FILEMARKER
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]