Skip to content

Commit 199c5ff

Browse files
authored
Merge pull request #2 from overleaf/msm-rebase-v2
Rebase `lts` branch with `upstream/v2` (former `lts` branch)
2 parents e1df247 + b419f27 commit 199c5ff

File tree

7 files changed

+277
-6
lines changed

7 files changed

+277
-6
lines changed

.github/workflows/ci.yml

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
name: ci
2+
3+
on:
4+
- pull_request
5+
- push
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
name:
14+
- Node.js 10.x
15+
- Node.js 11.x
16+
- Node.js 12.x
17+
- Node.js 13.x
18+
- Node.js 14.x
19+
- Node.js 15.x
20+
- Node.js 16.x
21+
- Node.js 17.x
22+
- Node.js 18.x
23+
- Node.js 19.x
24+
- Node.js 20.x
25+
- Node.js 21.x
26+
- Node.js 22.x
27+
- Node.js 23.x
28+
- Node.js 24.x
29+
30+
include:
31+
- name: Node.js 10.x
32+
node-version: "10.24"
33+
34+
35+
- name: Node.js 11.x
36+
node-version: "11.15"
37+
38+
39+
- name: Node.js 12.x
40+
node-version: "12.22"
41+
42+
43+
- name: Node.js 13.x
44+
node-version: "13.14"
45+
46+
47+
- name: Node.js 14.x
48+
node-version: "14.21"
49+
50+
51+
- name: Node.js 15.x
52+
node-version: "15.14"
53+
54+
55+
- name: Node.js 16.x
56+
node-version: "16.20"
57+
58+
- name: Node.js 17.x
59+
node-version: "17.9"
60+
61+
- name: Node.js 18.x
62+
node-version: "18.18"
63+
64+
- name: Node.js 19.x
65+
node-version: "19.9"
66+
67+
- name: Node.js 20.x
68+
node-version: "20.9"
69+
70+
- name: Node.js 21.x
71+
node-version: "21"
72+
73+
- name: Node.js 22.x
74+
node-version: "22"
75+
76+
- name: Node.js 23.x
77+
node-version: "23"
78+
79+
- name: Node.js 24.x
80+
node-version: "24"
81+
82+
steps:
83+
- uses: actions/checkout@v4
84+
85+
- name: Install Node.js ${{ matrix.node-version }}
86+
shell: bash -eo pipefail -l {0}
87+
run: |
88+
nvm install --default ${{ matrix.node-version }}
89+
if [[ "${{ matrix.node-version }}" == 0.* && "$(cut -d. -f2 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then
90+
nvm install --alias=npm 0.10
91+
nvm use ${{ matrix.node-version }}
92+
if [[ "$(npm -v)" == 1.1.* ]]; then
93+
nvm exec npm npm install -g [email protected]
94+
ln -fs "$(which npm)" "$(dirname "$(nvm which npm)")/npm"
95+
else
96+
sed -i '1s;^.*$;'"$(printf '#!%q' "$(nvm which npm)")"';' "$(readlink -f "$(which npm)")"
97+
fi
98+
npm config set strict-ssl false
99+
fi
100+
dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH"
101+
102+
- name: Remove npm module(s) ${{ matrix.npm-rm }}
103+
run: npm rm --silent --save-dev ${{ matrix.npm-rm }}
104+
if: matrix.npm-rm != ''
105+
106+
- name: Install npm module(s) ${{ matrix.npm-i }}
107+
run: npm install --save-dev ${{ matrix.npm-i }}
108+
if: matrix.npm-i != ''
109+
110+
- name: Install Node.js dependencies
111+
run: npm install
112+
113+
- name: List environment
114+
id: list_env
115+
shell: bash
116+
run: |
117+
echo "node@$(node -v)"
118+
echo "npm@$(npm -v)"
119+
npm -s ls ||:
120+
(npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT"
121+
122+
- name: Lint code
123+
run: npm run lint
124+
125+
- name: Run tests
126+
shell: bash
127+
run: |
128+
if npm -ps ls nyc | grep -q nyc; then
129+
npm run test-ci
130+
else
131+
npm test
132+
fi
133+
134+
- name: Collect code coverage
135+
uses: coverallsapp/github-action@master
136+
if: steps.list_env.outputs.nyc != ''
137+
with:
138+
github-token: ${{ secrets.GITHUB_TOKEN }}
139+
flag-name: run-${{ matrix.test_number }}
140+
parallel: true
141+
142+
coverage:
143+
needs: test
144+
runs-on: ubuntu-latest
145+
steps:
146+
- name: Upload code coverage
147+
uses: coverallsapp/github-action@master
148+
with:
149+
github-token: ${{ secrets.GITHUB_TOKEN }}
150+
parallel-finished: true

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,20 @@
33
All notable changes to this project will be documented in this file.
44
This project adheres to [Semantic Versioning](http://semver.org/).
55

6+
## 2.0.0
7+
8+
- **Breaking change: The minimum supported Node version is now 10.16.0**
9+
- Fix [CVE-2025-47935](https://www.cve.org/CVERecord?id=CVE-2025-47935) ([GHSA-44fp-w29j-9vj5](https://github.com/expressjs/multer/security/advisories/GHSA-44fp-w29j-9vj5))
10+
- Fix [CVE-2025-47944](https://www.cve.org/CVERecord?id=CVE-2025-47944) ([GHSA-4pg4-qvpc-4q3h](https://github.com/expressjs/multer/security/advisories/GHSA-4pg4-qvpc-4q3h))
11+
12+
## 1.4.5-lts.2
13+
14+
- Fix out-of-band error event from busboy (#1177)
15+
616
## 1.4.5-lts.1
717

818
- No changes
19+
920
## 1.4.4-lts.1
1021

1122
- Bugfix: Bump busboy to fix CVE-2022-24434 (#1097)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
1+
# Multer [![Build Status](https://badgen.net/github/checks/expressjs/multer/master?label=ci)](https://github.com/expressjs/multer/actions/workflows/ci.yml) [![Test Coverage](https://badgen.net/coveralls/c/github/expressjs/multer/master)](https://coveralls.io/r/expressjs/multer?branch=master) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
22

33
Multer is a node.js middleware for handling `multipart/form-data`, which is primarily used for uploading files. It is written
44
on top of [busboy](https://github.com/mscdex/busboy) for maximum efficiency.

lib/make-middleware.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ var MulterError = require('./multer-error')
88
var FileAppender = require('./file-appender')
99
var removeUploadedFiles = require('./remove-uploaded-files')
1010

11+
function drainStream (stream) {
12+
stream.on('readable', () => {
13+
while (stream.read() !== null) {}
14+
})
15+
}
16+
1117
function makeMiddleware (setup) {
1218
return function multerMiddleware (req, res, next) {
1319
if (!is(req, ['multipart'])) return next()
@@ -22,6 +28,10 @@ function makeMiddleware (setup) {
2228

2329
req.body = Object.create(null)
2430

31+
req.on('error', function (err) {
32+
abortWithError(err)
33+
})
34+
2535
var busboy
2636

2737
try {
@@ -41,7 +51,11 @@ function makeMiddleware (setup) {
4151
if (isDone) return
4252
isDone = true
4353
req.unpipe(busboy)
44-
busboy.removeAllListeners()
54+
drainStream(req)
55+
req.resume()
56+
setImmediate(() => {
57+
busboy.removeAllListeners()
58+
})
4559
next(err)
4660
}
4761

package.json

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "multer",
33
"description": "Middleware for handling `multipart/form-data`.",
4-
"version": "1.4.5-lts.1",
4+
"version": "2.0.0",
55
"contributors": [
66
"Hage Yaapa <[email protected]> (http://www.hacksparrow.com)",
77
"Jaret Pfluger <https://github.com/jpfluger>",
@@ -32,13 +32,13 @@
3232
"express": "^4.13.1",
3333
"form-data": "^1.0.0-rc1",
3434
"fs-temp": "^1.1.2",
35-
"mocha": "^3.5.3",
35+
"mocha": "^11.3.0",
3636
"rimraf": "^2.4.1",
3737
"standard": "^14.3.3",
3838
"testdata-w3c-json-form": "^1.0.0"
3939
},
4040
"engines": {
41-
"node": ">= 6.0.0"
41+
"node": ">= 10.16.0"
4242
},
4343
"files": [
4444
"LICENSE",
@@ -47,6 +47,10 @@
4747
"lib/"
4848
],
4949
"scripts": {
50-
"test": "standard && mocha"
50+
"lint": "standard",
51+
"lint:fix": "standard --fix",
52+
"test": "mocha --reporter spec --exit --check-leaks test/",
53+
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
54+
"test-cov": "nyc --reporter=html --reporter=text npm test"
5155
}
5256
}

test/express-integration.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-env mocha */
22

33
var assert = require('assert')
4+
var http = require('http')
45

56
var multer = require('../')
67
var util = require('./_util')
@@ -105,4 +106,94 @@ describe('Express Integration', function () {
105106
done()
106107
})
107108
})
109+
110+
it('should not crash on malformed request', function (done) {
111+
var upload = multer()
112+
113+
app.post('/upload', upload.single('file'), function (req, res) {
114+
res.status(500).end('Request should not be processed')
115+
})
116+
117+
app.use(function (err, req, res, next) {
118+
assert.strictEqual(err.message, 'Unexpected end of form')
119+
res.status(200).end('Correct error')
120+
})
121+
122+
var boundary = 'AaB03x'
123+
var body = [
124+
'--' + boundary,
125+
'Content-Disposition: form-data; name="file"; filename="test.txt"',
126+
'Content-Type: text/plain',
127+
'',
128+
'test without end boundary'
129+
].join('\r\n')
130+
var options = {
131+
hostname: 'localhost',
132+
port,
133+
path: '/upload',
134+
method: 'POST',
135+
headers: {
136+
'content-type': 'multipart/form-data; boundary=' + boundary,
137+
'content-length': body.length
138+
}
139+
}
140+
141+
var req = http.request(options, (res) => {
142+
assert.strictEqual(res.statusCode, 200)
143+
done()
144+
})
145+
146+
req.on('error', (err) => {
147+
done(err)
148+
})
149+
150+
req.write(body)
151+
req.end()
152+
})
153+
154+
it('should not crash on malformed request that causes two errors to be emitted by busboy', function (done) {
155+
var upload = multer()
156+
157+
app.post('/upload2', upload.single('file'), function (req, res) {
158+
res.status(500).end('Request should not be processed')
159+
})
160+
161+
app.use(function (err, req, res, next) {
162+
assert.strictEqual(err.message, 'Malformed part header')
163+
res.status(200).end('Correct error')
164+
})
165+
166+
var boundary = 'AaB03x'
167+
// this payload causes two errors to be emitted by busboy: `Malformed part header` and `Unexpected end of form`
168+
var body = [
169+
'--' + boundary,
170+
'Content-Disposition: form-data; name="file"; filename="test.txt"',
171+
'Content-Type: text/plain',
172+
'',
173+
'--' + boundary + '--',
174+
''
175+
].join('\r\n')
176+
var options = {
177+
hostname: 'localhost',
178+
port,
179+
path: '/upload2',
180+
method: 'POST',
181+
headers: {
182+
'content-type': 'multipart/form-data; boundary=' + boundary,
183+
'content-length': body.length
184+
}
185+
}
186+
187+
var req = http.request(options, (res) => {
188+
assert.strictEqual(res.statusCode, 200)
189+
done()
190+
})
191+
192+
req.on('error', (err) => {
193+
done(err)
194+
})
195+
196+
req.write(body)
197+
req.end()
198+
})
108199
})

0 commit comments

Comments
 (0)