@@ -100,6 +100,8 @@ const {
100
100
inspect : utilInspect ,
101
101
} = require ( 'internal/util/inspect' ) ;
102
102
103
+ const assert = require ( 'internal/assert' ) ;
104
+
103
105
const {
104
106
codes : {
105
107
ERR_BUFFER_OUT_OF_BOUNDS ,
@@ -205,6 +207,7 @@ function toInteger(n, defaultVal) {
205
207
return defaultVal ;
206
208
}
207
209
210
+
208
211
function copyImpl ( source , target , targetStart , sourceStart , sourceEnd ) {
209
212
if ( ! ArrayBufferIsView ( source ) )
210
213
throw new ERR_INVALID_ARG_TYPE ( 'source' , [ 'Buffer' , 'Uint8Array' ] , source ) ;
@@ -235,27 +238,45 @@ function copyImpl(source, target, targetStart, sourceStart, sourceEnd) {
235
238
throw new ERR_OUT_OF_RANGE ( 'sourceEnd' , '>= 0' , sourceEnd ) ;
236
239
}
237
240
241
+ // Clamp sourceEnd to be inbounds of source buffer.
242
+ // This is expected behavior and not to throw.
243
+ sourceEnd = MathMin ( sourceEnd , source . byteLength ) ;
244
+
238
245
if ( targetStart >= target . byteLength || sourceStart >= sourceEnd )
239
246
return 0 ;
240
247
241
- return _copyActual ( source , target , targetStart , sourceStart , sourceEnd ) ;
242
- }
243
-
244
- function _copyActual ( source , target , targetStart , sourceStart , sourceEnd ) {
245
- if ( sourceEnd - sourceStart > target . byteLength - targetStart )
246
- sourceEnd = sourceStart + target . byteLength - targetStart ;
248
+ // Assert source slice in bounds of source buffer.
249
+ // 0 <= sourceStart < sourceEnd <= source.byteLength
250
+ assert ( 0 <= sourceStart && sourceStart < sourceEnd && sourceEnd <= source . byteLength ) ;
247
251
248
- let nb = sourceEnd - sourceStart ;
249
- const sourceLen = source . byteLength - sourceStart ;
250
- if ( nb > sourceLen )
251
- nb = sourceLen ;
252
+ // Assert target slice in bounds of target buffer.
253
+ // 0 <= targetStart < target.byteLength
254
+ assert ( 0 <= targetStart && targetStart < target . byteLength ) ;
252
255
253
- if ( nb <= 0 )
254
- return 0 ;
256
+ // Truncate source so that its length doesn't exceed targets.
257
+ // This is the expected behavior, not to throw.
258
+ const copyLength = MathMin ( sourceEnd - sourceStart , target . byteLength - targetStart ) ;
259
+ sourceEnd = sourceStart + copyLength ;
255
260
256
- _copy ( source , target , targetStart , sourceStart , nb ) ;
261
+ return _copyActual ( source , target , targetStart , sourceStart , sourceStart + copyLength ) ;
262
+ }
257
263
258
- return nb ;
264
+ // Safely performs native copy from valid source slice to valid target slice.
265
+ // - The source slice is not clamped to fit into the target slice. If it won't fit, this throws.
266
+ // - If either the source or target slice are out of bounds, this throws.
267
+ function _copyActual ( source , target , targetStart , sourceStart , sourceEnd ) {
268
+ assert ( isUint8Array ( source ) && isUint8Array ( target ) ) ;
269
+ // Enforce: 0 <= sourceStart <= sourceEnd <= source.byteLength
270
+ assert ( 0 <= sourceStart && sourceStart <= sourceEnd && sourceEnd <= source . byteLength ) ;
271
+ // Enforce: 0 <= targetStart<= target.byteLength
272
+ assert ( 0 <= targetStart && targetStart <= target . byteLength ) ;
273
+
274
+ const copyLength = sourceEnd - sourceStart ;
275
+ const targetCapacity = target . byteLength - targetStart ;
276
+ assert ( copyLength <= targetCapacity ) ;
277
+
278
+ _copy ( source , target , targetStart , sourceStart , copyLength ) ;
279
+ return copyLength ;
259
280
}
260
281
261
282
/**
@@ -602,7 +623,9 @@ Buffer.concat = function concat(list, length) {
602
623
throw new ERR_INVALID_ARG_TYPE (
603
624
`list[${ i } ]` , [ 'Buffer' , 'Uint8Array' ] , list [ i ] ) ;
604
625
}
605
- pos += _copyActual ( buf , buffer , pos , 0 , buf . length ) ;
626
+
627
+ const copyLength = MathMin ( buf . length , buffer . length - pos ) ;
628
+ pos += _copyActual ( buf , buffer , pos , 0 , copyLength ) ;
606
629
}
607
630
608
631
// Note: `length` is always equal to `buffer.length` at this point
0 commit comments