@@ -1949,6 +1949,31 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
1949
1949
}
1950
1950
}
1951
1951
1952
+ static inline bool CheckOpenPermissions (Environment* env,
1953
+ const BufferValue& path,
1954
+ int flags) {
1955
+ // These flags capture the intention of the open() call.
1956
+ const int rwflags = flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
1957
+
1958
+ // These flags have write-like side effects even with O_RDONLY, at least on
1959
+ // some operating systems. On Windows, for example, O_RDONLY | O_TEMPORARY
1960
+ // can be used to delete a file. Bizarre.
1961
+ const int write_as_side_effect = flags & (UV_FS_O_APPEND | UV_FS_O_CREAT |
1962
+ UV_FS_O_TRUNC | UV_FS_O_TEMPORARY);
1963
+
1964
+ // TODO(rafaelgss): it can be optimized to avoid two permission checks
1965
+ auto pathView = path.ToStringView ();
1966
+ if (rwflags != UV_FS_O_WRONLY) {
1967
+ THROW_IF_INSUFFICIENT_PERMISSIONS (
1968
+ env, permission::PermissionScope::kFileSystemRead , pathView, false );
1969
+ }
1970
+ if (rwflags != UV_FS_O_RDONLY || write_as_side_effect) {
1971
+ THROW_IF_INSUFFICIENT_PERMISSIONS (
1972
+ env, permission::PermissionScope::kFileSystemWrite , pathView, false );
1973
+ }
1974
+ return true ;
1975
+ }
1976
+
1952
1977
static void Open (const FunctionCallbackInfo<Value>& args) {
1953
1978
Environment* env = Environment::GetCurrent (args);
1954
1979
@@ -1964,22 +1989,7 @@ static void Open(const FunctionCallbackInfo<Value>& args) {
1964
1989
CHECK (args[2 ]->IsInt32 ());
1965
1990
const int mode = args[2 ].As <Int32>()->Value ();
1966
1991
1967
- auto pathView = path.ToStringView ();
1968
- // Open can be called either in write or read
1969
- if (flags == O_RDWR) {
1970
- // TODO(rafaelgss): it can be optimized to avoid O(2*n)
1971
- THROW_IF_INSUFFICIENT_PERMISSIONS (
1972
- env, permission::PermissionScope::kFileSystemRead , pathView);
1973
- THROW_IF_INSUFFICIENT_PERMISSIONS (
1974
- env, permission::PermissionScope::kFileSystemWrite , pathView);
1975
- } else if ((flags & ~(UV_FS_O_RDONLY | UV_FS_O_SYNC)) == 0 ) {
1976
- THROW_IF_INSUFFICIENT_PERMISSIONS (
1977
- env, permission::PermissionScope::kFileSystemRead , pathView);
1978
- } else if ((flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC | UV_FS_O_CREAT |
1979
- UV_FS_O_WRONLY)) != 0 ) {
1980
- THROW_IF_INSUFFICIENT_PERMISSIONS (
1981
- env, permission::PermissionScope::kFileSystemWrite , pathView);
1982
- }
1992
+ if (!CheckOpenPermissions (env, path, flags)) return ;
1983
1993
1984
1994
FSReqBase* req_wrap_async = GetReqWrap (args, 3 );
1985
1995
if (req_wrap_async != nullptr ) { // open(path, flags, mode, req)
@@ -2010,31 +2020,14 @@ static void OpenFileHandle(const FunctionCallbackInfo<Value>& args) {
2010
2020
2011
2021
BufferValue path (isolate, args[0 ]);
2012
2022
CHECK_NOT_NULL (*path);
2013
- auto pathView = path.ToStringView ();
2014
- THROW_IF_INSUFFICIENT_PERMISSIONS (
2015
- env, permission::PermissionScope::kFileSystemRead , pathView);
2016
2023
2017
2024
CHECK (args[1 ]->IsInt32 ());
2018
2025
const int flags = args[1 ].As <Int32>()->Value ();
2019
2026
2020
2027
CHECK (args[2 ]->IsInt32 ());
2021
2028
const int mode = args[2 ].As <Int32>()->Value ();
2022
2029
2023
- // Open can be called either in write or read
2024
- if (flags == O_RDWR) {
2025
- // TODO(rafaelgss): it can be optimized to avoid O(2*n)
2026
- THROW_IF_INSUFFICIENT_PERMISSIONS (
2027
- env, permission::PermissionScope::kFileSystemRead , pathView);
2028
- THROW_IF_INSUFFICIENT_PERMISSIONS (
2029
- env, permission::PermissionScope::kFileSystemWrite , pathView);
2030
- } else if ((flags & ~(UV_FS_O_RDONLY | UV_FS_O_SYNC)) == 0 ) {
2031
- THROW_IF_INSUFFICIENT_PERMISSIONS (
2032
- env, permission::PermissionScope::kFileSystemRead , pathView);
2033
- } else if ((flags & (UV_FS_O_APPEND | UV_FS_O_TRUNC | UV_FS_O_CREAT |
2034
- UV_FS_O_WRONLY)) != 0 ) {
2035
- THROW_IF_INSUFFICIENT_PERMISSIONS (
2036
- env, permission::PermissionScope::kFileSystemWrite , pathView);
2037
- }
2030
+ if (!CheckOpenPermissions (env, path, flags)) return ;
2038
2031
2039
2032
FSReqBase* req_wrap_async = GetReqWrap (args, 3 );
2040
2033
if (req_wrap_async != nullptr ) { // openFileHandle(path, flags, mode, req)
0 commit comments