Skip to content

Commit

Permalink
Merge pull request #50 from vapor/update-with-vapor-bugfix
Browse files Browse the repository at this point in the history
BUG FIX: Multipart/form-data crashed if data was missing
  • Loading branch information
siemensikkema authored Jan 21, 2021
2 parents 24ad9eb + 423f5d8 commit 445e32f
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 31 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/api-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: deploy-api-docs
on:
push:
branches:
- master

jobs:
deploy:
name: api.vapor.codes
runs-on: ubuntu-latest
steps:
- name: Deploy api-docs
uses: appleboy/ssh-action@master
with:
host: vapor.codes
username: vapor
key: ${{ secrets.VAPOR_CODES_SSH_KEY }}
script: ./github-actions/deploy-api-docs.sh
command_timeout: 60m
41 changes: 28 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
name: test
on:
- pull_request
on: { pull_request: {} }

jobs:
xenial:
container:
image: vapor/swift:5.1-xenial
getcidata:
runs-on: ubuntu-latest
outputs:
environments: ${{ steps.output.outputs.environments }}
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery --sanitize=thread
bionic:
container:
image: vapor/swift:5.1-bionic
runs-on: ubuntu-latest
- id: output
run: |
envblob="$(curl -fsSL https://raw.githubusercontent.com/vapor/ci/main/pr-environments.json | jq -cMj '.')"
echo "::set-output name=environments::${envblob}"
test-vapor:
needs: getcidata
strategy:
fail-fast: false
matrix:
env: ${{ fromJSON(needs.getcidata.outputs.environments) }}
runs-on: ${{ matrix.env.os }}
container: ${{ matrix.env.image }}
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery --sanitize=thread
- name: Select toolchain
uses: maxim-lobanov/[email protected]
with:
xcode-version: ${{ matrix.env.toolchain }}
if: ${{ matrix.env.toolchain != '' }}
- name: Check out Vapor
uses: actions/checkout@v2
- name: Run tests with Thread Sanitizer
timeout-minutes: 20
run: swift test --enable-test-discovery --sanitize=thread
10 changes: 5 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// swift-tools-version:5.1
// swift-tools-version:5.2
import PackageDescription

let package = Package(
name: "multipart-kit",
platforms: [
.macOS(.v10_14)
.macOS(.v10_15)
],
products: [
.library(name: "MultipartKit", targets: ["MultipartKit"]),
Expand All @@ -15,9 +15,9 @@ let package = Package(
targets: [
.target(name: "CMultipartParser"),
.target(name: "MultipartKit", dependencies: [
"NIO",
"NIOHTTP1",
"CMultipartParser",
.product(name: "NIO", package: "swift-nio"),
.product(name: "NIOHTTP1", package: "swift-nio"),
.target(name: "CMultipartParser"),
]),
.testTarget(name: "MultipartKitTests", dependencies: ["MultipartKit"]),
]
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img src="https://user-images.githubusercontent.com/1342803/38707794-e50a4bda-3e80-11e8-850b-5a3088797edf.png" height="64" alt="Multipart">
<br>
<br>
<a href="https://docs.vapor.codes/3.0/multipart/getting-started/">
<a href="https://docs.vapor.codes/4.0/">
<img src="http://img.shields.io/badge/read_the-docs-2196f3.svg" alt="Documentation">
</a>
<a href="https://discord.gg/vapor">
Expand All @@ -11,10 +11,13 @@
<a href="LICENSE">
<img src="http://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT License">
</a>
<a href="https://circleci.com/gh/vapor/multipart">
<img src="https://circleci.com/gh/vapor/multipart.svg?style=shield" alt="Continuous Integration">
<a href="https://github.com/vapor/multipart-kit/actions">
<img src="https://github.com/vapor/multipart-kit/workflows/test/badge.svg" alt="Continuous Integration">
</a>
<a href="https://swift.org">
<img src="http://img.shields.io/badge/swift-4.1-brightgreen.svg" alt="Swift 4.1">
<img src="http://img.shields.io/badge/swift-5.2-brightgreen.svg" alt="Swift 5.2">
</a>
<a href="https://twitter.com/codevapor">
<img src="https://img.shields.io/badge/twitter-codevapor-5AA9E7.svg" alt="Twitter">
</a>
</p>
5 changes: 4 additions & 1 deletion Sources/MultipartKit/FormDataDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ private final class FormDataDecoderContext {
guard let offset = codingPath[1].intValue else {
throw MultipartError.nesting
}
part = parts.allParts(named: name)[offset]
guard let p = parts.allParts(named: name)[safe: offset] else {
throw MultipartError.missingPart("\(codingPath[1].stringValue)")
}
part = p
default:
throw MultipartError.nesting
}
Expand Down
12 changes: 4 additions & 8 deletions Sources/MultipartKit/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,15 @@ extension HTTPHeaders {
}
}



extension CharacterSet {
static var quotes: CharacterSet {
return .init(charactersIn: #""'"#)
}
}

extension DataProtocol {
func copyBytes() -> [UInt8] {
var buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: self.count)
self.copyBytes(to: buffer)
defer { buffer.deallocate() }
return .init(buffer)
extension Collection {
/// Returns the element at the specified index if it is within bounds, otherwise nil.
subscript (safe index: Index) -> Element? {
self.indices.contains(index) ? self[index] : nil
}
}
24 changes: 24 additions & 0 deletions Tests/MultipartKitTests/MultipartKitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,30 @@ class MultipartTests: XCTestCase {
XCTAssertEqual(data, "--123\r\n\r\nfoo\r\n--123--\r\n")
}
}

func testFormDataDecoderMultipleWithMissingData() {
/// Content-Type: multipart/form-data; boundary=hello
let data = """
--hello\r\n\
Content-Disposition: form-data; name="link"\r\n\
\r\n\
https://google.com\r\n\
--hello--\r\n
"""

struct Foo: Decodable {
var link: URL
}

XCTAssertThrowsError(try FormDataDecoder().decode(Foo.self, from: data, boundary: "hello")) { error in
guard case let MultipartError.missingPart(array) = error else {
XCTFail("Was expecting an error of type MultipartError.missingPart")
return
}

XCTAssertEqual(array, "relative")
}
}
}

// https://stackoverflow.com/a/54524110/1041105
Expand Down

0 comments on commit 445e32f

Please sign in to comment.