| ... | ... | @@ -95,13 +95,23 @@ export class EnvironmentThemeService extends Context.Service< |
| 95 | 95 | * usable, a symlinked file inside it does not), O_NONBLOCK keeps a FIFO from |
| 96 | 96 | * blocking the open, and the fstat type and size gate examines the open |
| 97 | 97 | * descriptor. Returns null for anything that is not a small regular file. |
| 98 | * |
| 99 | * Windows has neither flag (the constants are undefined, and OR-ing them in |
| 100 | * is a no-op), so the symlink check there is an lstat before the open. That |
| 101 | * leaves a window a swap could slip through, which the descriptor-bound |
| 102 | * checks below then narrow to "a regular file at that path". |
| 98 | 103 | */ |
| 99 | 104 | export const readThemeFileGuarded = (filePath: string, maxBytes: number): string | null => { |
| 100 | 105 | let fd: number; |
| 101 | 106 | try { |
| 107 | if (NodeFS.constants.O_NOFOLLOW === undefined && NodeFS.lstatSync(filePath).isSymbolicLink()) { |
| 108 | return null; |
| 109 | } |
| 102 | 110 | fd = NodeFS.openSync( |
| 103 | 111 | filePath, |
| 104 | | NodeFS.constants.O_RDONLY | NodeFS.constants.O_NOFOLLOW | NodeFS.constants.O_NONBLOCK, |
| 112 | NodeFS.constants.O_RDONLY | |
| 113 | (NodeFS.constants.O_NOFOLLOW ?? 0) | |
| 114 | (NodeFS.constants.O_NONBLOCK ?? 0), |
| 105 | 115 | ); |
| 106 | 116 | } catch { |
| 107 | 117 | return null; |