@@ -81,6 +81,16 @@ function throwOptionsError(options) {
81
81
'but got ' + typeof options + ' instead' ) ;
82
82
}
83
83
84
+ function isFD ( fd ) {
85
+ return Number . isInteger ( fd ) && fd >= 0 && fd <= 0xFFFFFFFF ;
86
+ }
87
+
88
+ function sanitizeFD ( fd ) {
89
+ if ( ! isFD ( fd ) )
90
+ throw new TypeError ( 'file descriptor must be a unsigned 32-bit integer' ) ;
91
+ return fd ;
92
+ }
93
+
84
94
// Ensure that callbacks run in the global context. Only use this function
85
95
// for callbacks that are passed to the binding layer, callbacks that are
86
96
// invoked from JS already run in the proper scope.
@@ -112,10 +122,6 @@ function nullCheck(path, callback) {
112
122
return true ;
113
123
}
114
124
115
- function isFd ( path ) {
116
- return ( path >>> 0 ) === path ;
117
- }
118
-
119
125
// Static method to set the stats properties on a Stats object.
120
126
fs . Stats = function (
121
127
dev ,
@@ -257,7 +263,7 @@ fs.readFile = function(path, options, callback) {
257
263
return ;
258
264
259
265
var context = new ReadFileContext ( callback , encoding ) ;
260
- context . isUserFd = isFd ( path ) ; // file descriptor ownership
266
+ context . isUserFd = isFD ( path ) ; // file descriptor ownership
261
267
var req = new FSReqWrap ( ) ;
262
268
req . context = context ;
263
269
req . oncomplete = readFileAfterOpen ;
@@ -473,7 +479,7 @@ fs.readFileSync = function(path, options) {
473
479
assertEncoding ( encoding ) ;
474
480
475
481
var flag = options . flag || 'r' ;
476
- var isUserFd = isFd ( path ) ; // file descriptor ownership
482
+ var isUserFd = isFD ( path ) ; // file descriptor ownership
477
483
var fd = isUserFd ? path : fs . openSync ( path , flag , 0o666 ) ;
478
484
479
485
var st = tryStatSync ( fd , isUserFd ) ;
@@ -570,12 +576,12 @@ Object.defineProperty(exports, '_stringToFlags', {
570
576
571
577
fs . close = function ( fd , callback ) {
572
578
var req = new FSReqWrap ( ) ;
573
- req . oncomplete = makeCallback ( arguments [ arguments . length - 1 ] ) ;
574
- binding . close ( fd , req ) ;
579
+ req . oncomplete = makeCallback ( callback ) ;
580
+ binding . close ( sanitizeFD ( fd ) , req ) ;
575
581
} ;
576
582
577
583
fs . closeSync = function ( fd ) {
578
- return binding . close ( fd ) ;
584
+ return binding . close ( sanitizeFD ( fd ) ) ;
579
585
} ;
580
586
581
587
function modeNum ( m , def ) {
@@ -612,6 +618,7 @@ fs.openSync = function(path, flags, mode) {
612
618
var readWarned = false ;
613
619
fs . read = function ( fd , buffer , offset , length , position , callback ) {
614
620
callback = makeCallback ( arguments [ arguments . length - 1 ] ) ;
621
+ fd = sanitizeFD ( fd ) ;
615
622
if ( ! ( buffer instanceof Buffer ) ) {
616
623
// legacy string interface (fd, length, position, encoding, callback)
617
624
readWarned = printDeprecation ( 'fs.read\'s legacy String interface ' +
@@ -672,6 +679,7 @@ fs.readSync = function(fd, buffer, offset, length, position) {
672
679
var legacy = false ;
673
680
var encoding ;
674
681
682
+ fd = sanitizeFD ( fd ) ;
675
683
if ( ! ( buffer instanceof Buffer ) ) {
676
684
// legacy string interface (fd, length, position, encoding, callback)
677
685
readSyncWarned = printDeprecation ( 'fs.readSync\'s legacy String interface' +
@@ -713,6 +721,7 @@ fs.readSync = function(fd, buffer, offset, length, position) {
713
721
// fs.write(fd, string[, position[, encoding]], callback);
714
722
fs . write = function ( fd , buffer , offset , length , position , callback ) {
715
723
callback = makeCallback ( arguments [ arguments . length - 1 ] ) ;
724
+ fd = sanitizeFD ( fd ) ;
716
725
function wrapper ( err , written ) {
717
726
// Retain a reference to buffer so that it can't be GC'ed too soon.
718
727
callback ( err , written || 0 , buffer ) ;
@@ -748,6 +757,7 @@ fs.write = function(fd, buffer, offset, length, position, callback) {
748
757
// OR
749
758
// fs.writeSync(fd, string[, position[, encoding]]);
750
759
fs . writeSync = function ( fd , buffer , offset , length , position ) {
760
+ fd = sanitizeFD ( fd ) ;
751
761
if ( buffer instanceof Buffer ) {
752
762
if ( position === undefined )
753
763
position = null ;
@@ -779,14 +789,18 @@ fs.renameSync = function(oldPath, newPath) {
779
789
} ;
780
790
781
791
fs . truncate = function ( path , len , callback ) {
782
- if ( typeof path === 'number' ) {
792
+ callback = makeCallback ( arguments [ arguments . length - 1 ] ) ;
793
+
794
+ if ( isFD ( path ) )
783
795
return fs . ftruncate ( path , len , callback ) ;
784
- }
785
796
786
- callback = makeCallback ( arguments [ arguments . length - 1 ] ) ;
797
+ if ( typeof path !== 'string' )
798
+ throw new TypeError ( 'path must be a string' ) ;
787
799
788
- if ( typeof len === 'function' || len === undefined ) {
800
+ if ( typeof len === 'function' || len == undefined ) {
789
801
len = 0 ;
802
+ } else if ( ! Number . isInteger ( len ) || len < 0 ) {
803
+ throw new TypeError ( 'length must be a positive integer' ) ;
790
804
}
791
805
792
806
fs . open ( path , 'r+' , function ( er , fd ) {
@@ -802,13 +816,18 @@ fs.truncate = function(path, len, callback) {
802
816
} ;
803
817
804
818
fs . truncateSync = function ( path , len ) {
805
- if ( typeof path === 'number' ) {
806
- // legacy
819
+ if ( isFD ( path ) )
807
820
return fs . ftruncateSync ( path , len ) ;
808
- }
809
- if ( len === undefined ) {
821
+
822
+ if ( typeof path !== 'string' )
823
+ throw new TypeError ( 'path must be a string' ) ;
824
+
825
+ if ( len === undefined || len === null ) {
810
826
len = 0 ;
827
+ } else if ( ! Number . isInteger ( len ) || len < 0 ) {
828
+ throw new TypeError ( 'length must be a positive integer' ) ;
811
829
}
830
+
812
831
// allow error to be thrown, but still close fd.
813
832
var fd = fs . openSync ( path , 'r+' ) ;
814
833
var ret ;
@@ -822,18 +841,30 @@ fs.truncateSync = function(path, len) {
822
841
} ;
823
842
824
843
fs . ftruncate = function ( fd , len , callback ) {
825
- if ( typeof len === 'function' || len === undefined ) {
844
+ callback = makeCallback ( arguments [ arguments . length - 1 ] ) ;
845
+
846
+ fd = sanitizeFD ( fd ) ;
847
+
848
+ if ( typeof len === 'function' || len == undefined ) {
826
849
len = 0 ;
850
+ } else if ( ! Number . isInteger ( len ) || len < 0 ) {
851
+ throw new TypeError ( 'length must be a positive integer' ) ;
827
852
}
853
+
828
854
var req = new FSReqWrap ( ) ;
829
- req . oncomplete = makeCallback ( arguments [ arguments . length - 1 ] ) ;
855
+ req . oncomplete = callback ;
830
856
binding . ftruncate ( fd , len , req ) ;
831
857
} ;
832
858
833
859
fs . ftruncateSync = function ( fd , len ) {
834
- if ( len === undefined ) {
860
+ fd = sanitizeFD ( fd ) ;
861
+
862
+ if ( len === undefined || len === null ) {
835
863
len = 0 ;
864
+ } else if ( ! Number . isInteger ( len ) || len < 0 ) {
865
+ throw new TypeError ( 'length must be a positive integer' ) ;
836
866
}
867
+
837
868
return binding . ftruncate ( fd , len ) ;
838
869
} ;
839
870
@@ -853,21 +884,21 @@ fs.rmdirSync = function(path) {
853
884
fs . fdatasync = function ( fd , callback ) {
854
885
var req = new FSReqWrap ( ) ;
855
886
req . oncomplete = makeCallback ( callback ) ;
856
- binding . fdatasync ( fd , req ) ;
887
+ binding . fdatasync ( sanitizeFD ( fd ) , req ) ;
857
888
} ;
858
889
859
890
fs . fdatasyncSync = function ( fd ) {
860
- return binding . fdatasync ( fd ) ;
891
+ return binding . fdatasync ( sanitizeFD ( fd ) ) ;
861
892
} ;
862
893
863
894
fs . fsync = function ( fd , callback ) {
864
895
var req = new FSReqWrap ( ) ;
865
- req . oncomplete = makeCallback ( arguments [ arguments . length - 1 ] ) ;
866
- binding . fsync ( fd , req ) ;
896
+ req . oncomplete = makeCallback ( callback ) ;
897
+ binding . fsync ( sanitizeFD ( fd ) , req ) ;
867
898
} ;
868
899
869
900
fs . fsyncSync = function ( fd ) {
870
- return binding . fsync ( fd ) ;
901
+ return binding . fsync ( sanitizeFD ( fd ) ) ;
871
902
} ;
872
903
873
904
fs . mkdir = function ( path , mode , callback ) {
@@ -915,8 +946,8 @@ fs.readdirSync = function(path, options) {
915
946
916
947
fs . fstat = function ( fd , callback ) {
917
948
var req = new FSReqWrap ( ) ;
918
- req . oncomplete = makeCallback ( arguments [ arguments . length - 1 ] ) ;
919
- binding . fstat ( fd , req ) ;
949
+ req . oncomplete = makeCallback ( callback ) ;
950
+ binding . fstat ( sanitizeFD ( fd ) , req ) ;
920
951
} ;
921
952
922
953
fs . lstat = function ( path , callback ) {
@@ -936,7 +967,7 @@ fs.stat = function(path, callback) {
936
967
} ;
937
968
938
969
fs . fstatSync = function ( fd ) {
939
- return binding . fstat ( fd ) ;
970
+ return binding . fstat ( sanitizeFD ( fd ) ) ;
940
971
} ;
941
972
942
973
fs . lstatSync = function ( path ) {
@@ -1053,11 +1084,11 @@ fs.unlinkSync = function(path) {
1053
1084
fs . fchmod = function ( fd , mode , callback ) {
1054
1085
var req = new FSReqWrap ( ) ;
1055
1086
req . oncomplete = makeCallback ( arguments [ arguments . length - 1 ] ) ;
1056
- binding . fchmod ( fd , modeNum ( mode ) , req ) ;
1087
+ binding . fchmod ( sanitizeFD ( fd ) , modeNum ( mode ) , req ) ;
1057
1088
} ;
1058
1089
1059
1090
fs . fchmodSync = function ( fd , mode ) {
1060
- return binding . fchmod ( fd , modeNum ( mode ) ) ;
1091
+ return binding . fchmod ( sanitizeFD ( fd ) , modeNum ( mode ) ) ;
1061
1092
} ;
1062
1093
1063
1094
if ( constants . hasOwnProperty ( 'O_SYMLINK' ) ) {
@@ -1136,11 +1167,11 @@ if (constants.hasOwnProperty('O_SYMLINK')) {
1136
1167
fs . fchown = function ( fd , uid , gid , callback ) {
1137
1168
var req = new FSReqWrap ( ) ;
1138
1169
req . oncomplete = makeCallback ( arguments [ arguments . length - 1 ] ) ;
1139
- binding . fchown ( fd , uid , gid , req ) ;
1170
+ binding . fchown ( sanitizeFD ( fd ) , uid , gid , req ) ;
1140
1171
} ;
1141
1172
1142
1173
fs . fchownSync = function ( fd , uid , gid ) {
1143
- return binding . fchown ( fd , uid , gid ) ;
1174
+ return binding . fchown ( sanitizeFD ( fd ) , uid , gid ) ;
1144
1175
} ;
1145
1176
1146
1177
fs . chown = function ( path , uid , gid , callback ) {
@@ -1197,6 +1228,7 @@ fs.utimesSync = function(path, atime, mtime) {
1197
1228
1198
1229
fs . futimes = function ( fd , atime , mtime , callback ) {
1199
1230
callback = makeCallback ( arguments [ arguments . length - 1 ] ) ;
1231
+ fd = sanitizeFD ( fd ) ;
1200
1232
atime = toUnixTimestamp ( atime ) ;
1201
1233
mtime = toUnixTimestamp ( mtime ) ;
1202
1234
var req = new FSReqWrap ( ) ;
@@ -1205,6 +1237,7 @@ fs.futimes = function(fd, atime, mtime, callback) {
1205
1237
} ;
1206
1238
1207
1239
fs . futimesSync = function ( fd , atime , mtime ) {
1240
+ fd = sanitizeFD ( fd ) ;
1208
1241
atime = toUnixTimestamp ( atime ) ;
1209
1242
mtime = toUnixTimestamp ( mtime ) ;
1210
1243
binding . futimes ( fd , atime , mtime ) ;
@@ -1257,7 +1290,7 @@ fs.writeFile = function(path, data, options, callback) {
1257
1290
1258
1291
var flag = options . flag || 'w' ;
1259
1292
1260
- if ( isFd ( path ) ) {
1293
+ if ( isFD ( path ) ) {
1261
1294
writeFd ( path , true ) ;
1262
1295
return ;
1263
1296
}
@@ -1291,7 +1324,7 @@ fs.writeFileSync = function(path, data, options) {
1291
1324
assertEncoding ( options . encoding ) ;
1292
1325
1293
1326
var flag = options . flag || 'w' ;
1294
- var isUserFd = isFd ( path ) ; // file descriptor ownership
1327
+ var isUserFd = isFD ( path ) ; // file descriptor ownership
1295
1328
var fd = isUserFd ? path : fs . openSync ( path , flag , options . mode ) ;
1296
1329
1297
1330
if ( ! ( data instanceof Buffer ) ) {
@@ -1329,7 +1362,7 @@ fs.appendFile = function(path, data, options, callback) {
1329
1362
options = util . _extend ( { flag : 'a' } , options ) ;
1330
1363
1331
1364
// force append behavior when using a supplied file descriptor
1332
- if ( isFd ( path ) )
1365
+ if ( isFD ( path ) )
1333
1366
options . flag = 'a' ;
1334
1367
1335
1368
fs . writeFile ( path , data , options , callback ) ;
@@ -1348,7 +1381,7 @@ fs.appendFileSync = function(path, data, options) {
1348
1381
options = util . _extend ( { flag : 'a' } , options ) ;
1349
1382
1350
1383
// force append behavior when using a supplied file descriptor
1351
- if ( isFd ( path ) )
1384
+ if ( isFD ( path ) )
1352
1385
options . flag = 'a' ;
1353
1386
1354
1387
fs . writeFileSync ( path , data , options ) ;
@@ -1932,7 +1965,7 @@ function SyncWriteStream(fd, options) {
1932
1965
1933
1966
options = options || { } ;
1934
1967
1935
- this . fd = fd ;
1968
+ this . fd = sanitizeFD ( fd ) ;
1936
1969
this . writable = true ;
1937
1970
this . readable = false ;
1938
1971
this . autoClose = options . autoClose === undefined ? true : options . autoClose ;
0 commit comments