mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge #7561 'os_open: UV_EINVAL on NULL filename'
This commit is contained in:
		| @@ -133,22 +133,12 @@ bool os_isdir(const char_u *name) | |||||||
| int os_nodetype(const char *name) | int os_nodetype(const char *name) | ||||||
|   FUNC_ATTR_NONNULL_ALL |   FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
| #ifdef WIN32 | #ifndef WIN32  // Unix | ||||||
|   // Edge case from Vim os_win32.c: |  | ||||||
|   // We can't open a file with a name "\\.\con" or "\\.\prn", trying to read |  | ||||||
|   // from it later will cause Vim to hang. Thus return NODE_WRITABLE here. |  | ||||||
|   if (STRNCMP(name, "\\\\.\\", 4) == 0) { |  | ||||||
|     return NODE_WRITABLE; |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   uv_stat_t statbuf; |   uv_stat_t statbuf; | ||||||
|   if (0 != os_stat(name, &statbuf)) { |   if (0 != os_stat(name, &statbuf)) { | ||||||
|     return NODE_NORMAL;  // File doesn't exist. |     return NODE_NORMAL;  // File doesn't exist. | ||||||
|   } |   } | ||||||
|  |   // uv_handle_type does not distinguish BLK and DIR. | ||||||
| #ifndef WIN32 |  | ||||||
|   // libuv does not handle BLK and DIR in uv_handle_type. |  | ||||||
|   //    Related: https://github.com/joyent/libuv/pull/1421 |   //    Related: https://github.com/joyent/libuv/pull/1421 | ||||||
|   if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) { |   if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) { | ||||||
|     return NODE_NORMAL; |     return NODE_NORMAL; | ||||||
| @@ -156,48 +146,51 @@ int os_nodetype(const char *name) | |||||||
|   if (S_ISBLK(statbuf.st_mode)) {  // block device isn't writable |   if (S_ISBLK(statbuf.st_mode)) {  // block device isn't writable | ||||||
|     return NODE_OTHER; |     return NODE_OTHER; | ||||||
|   } |   } | ||||||
| #endif |   // Everything else is writable? | ||||||
|  |   // buf_write() expects NODE_WRITABLE for char device /dev/stderr. | ||||||
|   // Vim os_win32.c:mch_nodetype does this (since patch 7.4.015): |   return NODE_WRITABLE; | ||||||
|   //    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { | #else  // Windows | ||||||
|   //      wn = enc_to_utf16(name, NULL); |   // Edge case from Vim os_win32.c: | ||||||
|   //      hFile = CreatFile(wn, ...) |   // We can't open a file with a name "\\.\con" or "\\.\prn", trying to read | ||||||
|   // to get a HANDLE. But libuv just calls win32's _get_osfhandle() on the fd we |   // from it later will cause Vim to hang. Thus return NODE_WRITABLE here. | ||||||
|   // give it. uv_fs_open calls fs__capture_path which does a similar dance and |   if (STRNCMP(name, "\\\\.\\", 4) == 0) { | ||||||
|   // saves us the hassle. |     return NODE_WRITABLE; | ||||||
|  |  | ||||||
|   int nodetype = NODE_WRITABLE; |  | ||||||
|   int fd = os_open(name, O_RDONLY |  | ||||||
| #ifdef O_NONBLOCK |  | ||||||
|                    | O_NONBLOCK |  | ||||||
| #endif |  | ||||||
|                    , 0); |  | ||||||
|   if (fd == -1) { |  | ||||||
|     return NODE_OTHER;  // open() failed. |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   switch (uv_guess_handle(fd)) { |   // Vim os_win32.c:mch_nodetype does (since 7.4.015): | ||||||
|  |   //    wn = enc_to_utf16(name, NULL); | ||||||
|  |   //    hFile = CreatFile(wn, ...) | ||||||
|  |   // to get a HANDLE. Whereas libuv just calls _get_osfhandle() on the fd we | ||||||
|  |   // give it. But uv_fs_open later calls fs__capture_path which does a similar | ||||||
|  |   // utf8-to-utf16 dance and saves us the hassle. | ||||||
|  |  | ||||||
|  |   // macOS: os_open(/dev/stderr) would return UV_EACCES. | ||||||
|  |   int fd = os_open(name, O_RDONLY | ||||||
|  | # ifdef O_NONBLOCK | ||||||
|  |                    | O_NONBLOCK | ||||||
|  | # endif | ||||||
|  |                    , 0); | ||||||
|  |   if (fd < 0) {  // open() failed. | ||||||
|  |     return NODE_NORMAL; | ||||||
|  |   } | ||||||
|  |   int guess = uv_guess_handle(fd); | ||||||
|  |   if (close(fd) == -1) { | ||||||
|  |     ELOG("close(%d) failed. name='%s'", fd, name); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   switch (guess) { | ||||||
|     case UV_TTY:          // FILE_TYPE_CHAR |     case UV_TTY:          // FILE_TYPE_CHAR | ||||||
|       nodetype = NODE_WRITABLE; |       return NODE_WRITABLE; | ||||||
|       break; |  | ||||||
|     case UV_FILE:         // FILE_TYPE_DISK |     case UV_FILE:         // FILE_TYPE_DISK | ||||||
|       nodetype = NODE_NORMAL; |       return NODE_NORMAL; | ||||||
|       break; |  | ||||||
|     case UV_NAMED_PIPE:   // not handled explicitly in Vim os_win32.c |     case UV_NAMED_PIPE:   // not handled explicitly in Vim os_win32.c | ||||||
|     case UV_UDP:          // unix only |     case UV_UDP:          // unix only | ||||||
|     case UV_TCP:          // unix only |     case UV_TCP:          // unix only | ||||||
|     case UV_UNKNOWN_HANDLE: |     case UV_UNKNOWN_HANDLE: | ||||||
|     default: |     default: | ||||||
| #ifdef WIN32 |       return NODE_OTHER;  // Vim os_win32.c default | ||||||
|       nodetype = NODE_NORMAL; |  | ||||||
| #else |  | ||||||
|       nodetype = NODE_WRITABLE;  // Everything else is writable? |  | ||||||
| #endif |  | ||||||
|       break; |  | ||||||
|   } |   } | ||||||
|  | #endif | ||||||
|   close(fd); |  | ||||||
|   return nodetype; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Gets the absolute path of the currently running executable. | /// Gets the absolute path of the currently running executable. | ||||||
| @@ -394,9 +387,11 @@ end: | |||||||
| /// @param mode Permissions for the newly-created file (IGNORED if 'flags' is | /// @param mode Permissions for the newly-created file (IGNORED if 'flags' is | ||||||
| ///        not `O_CREAT` or `O_TMPFILE`), subject to the current umask | ///        not `O_CREAT` or `O_TMPFILE`), subject to the current umask | ||||||
| /// @return file descriptor, or libuv error code on failure | /// @return file descriptor, or libuv error code on failure | ||||||
| int os_open(const char* path, int flags, int mode) | int os_open(const char *path, int flags, int mode) | ||||||
|   FUNC_ATTR_NONNULL_ALL |  | ||||||
| { | { | ||||||
|  |   if (path == NULL) {  // uv_fs_open asserts on NULL. #7561 | ||||||
|  |     return UV_EINVAL; | ||||||
|  |   } | ||||||
|   int r; |   int r; | ||||||
|   RUN_UV_FS_FUNC(r, uv_fs_open, path, flags, mode, NULL); |   RUN_UV_FS_FUNC(r, uv_fs_open, path, flags, mode, NULL); | ||||||
|   return r; |   return r; | ||||||
| @@ -603,12 +598,12 @@ int os_fsync(int fd) | |||||||
|  |  | ||||||
| /// Get stat information for a file. | /// Get stat information for a file. | ||||||
| /// | /// | ||||||
| /// @return libuv return code. | /// @return libuv return code, or -errno | ||||||
| static int os_stat(const char *name, uv_stat_t *statbuf) | static int os_stat(const char *name, uv_stat_t *statbuf) | ||||||
|   FUNC_ATTR_NONNULL_ARG(2) |   FUNC_ATTR_NONNULL_ARG(2) | ||||||
| { | { | ||||||
|   if (!name) { |   if (!name) { | ||||||
|     return UV_ENOENT; |     return UV_EINVAL; | ||||||
|   } |   } | ||||||
|   uv_fs_t request; |   uv_fs_t request; | ||||||
|   int result = uv_fs_stat(&fs_loop, &request, name, NULL); |   int result = uv_fs_stat(&fs_loop, &request, name, NULL); | ||||||
| @@ -1078,7 +1073,8 @@ shortcut_end: | |||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| int os_translate_sys_error(int sys_errno) { | int os_translate_sys_error(int sys_errno) | ||||||
|  | { | ||||||
| #ifdef HAVE_UV_TRANSLATE_SYS_ERROR | #ifdef HAVE_UV_TRANSLATE_SYS_ERROR | ||||||
|   return uv_translate_sys_error(sys_errno); |   return uv_translate_sys_error(sys_errno); | ||||||
| #elif defined(WIN32) | #elif defined(WIN32) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes