{"action":"created","issue":{"url":"https://api.github.com/repos/libuv/libuv/issues/226","labels_url":"https://api.github.com/repos/libuv/libuv/issues/226/labels{/name}","comments_url":"https://api.github.com/repos/libuv/libuv/issues/226/comments","events_url":"https://api.github.com/repos/libuv/libuv/issues/226/events","html_url":"https://github.com/libuv/libuv/pull/226","id":58836033,"number":226,"title":"unix: spawn should protect its input fds","user":{"login":"sam-github","id":17607,"avatar_url":"https://avatars.githubusercontent.com/u/17607?v=3","gravatar_id":"","url":"https://api.github.com/users/sam-github","html_url":"https://github.com/sam-github","followers_url":"https://api.github.com/users/sam-github/followers","following_url":"https://api.github.com/users/sam-github/following{/other_user}","gists_url":"https://api.github.com/users/sam-github/gists{/gist_id}","starred_url":"https://api.github.com/users/sam-github/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sam-github/subscriptions","organizations_url":"https://api.github.com/users/sam-github/orgs","repos_url":"https://api.github.com/users/sam-github/repos","events_url":"https://api.github.com/users/sam-github/events{/privacy}","received_events_url":"https://api.github.com/users/sam-github/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-02-25T01:31:46Z","updated_at":"2015-02-25T09:47:39Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/libuv/libuv/pulls/226","html_url":"https://github.com/libuv/libuv/pull/226","diff_url":"https://github.com/libuv/libuv/pull/226.diff","patch_url":"https://github.com/libuv/libuv/pull/226.patch"},"body":"spawn allows copying descriptor numbers during exec, but it wasn't\r\nprotecting them. Under some conditions, such as swapping stdout and\r\nstderr, it would do this:\r\n\r\n dup 2 -> 1\r\n dup 1 -> 2\r\n\r\nWith end result that both 1 and 2 would be stderr, rather than being\r\nswapped.\r\n\r\nWith this change, the above sequence gets rewritten to:\r\n\r\n dup 1 -> 3\r\n dup 2 -> 1\r\n dup 3 -> 2\r\n\r\n\r\nThis fix can be verified against io.js. Using fd-dup.js:\r\n\r\n```\r\nvar cp = require('child_process');\r\nvar fs = require('fs');\r\n\r\nif (process.env.CHILD) {\r\n  console.log('STDOUT');\r\n  console.error('STDERR');\r\n  return;\r\n}\r\n\r\nvar options = {\r\n  stdio: [0, 2, 1],\r\n  env: { CHILD: true },\r\n};\r\nvar c = cp.spawn(process.execPath, [__filename], options);\r\n```\r\n\r\nWithout this patch both fd 1 and 2 in child end up in parent's stderr:\r\n\r\n```\r\n% ./iojs fd-dup.js 1>_1.txt 2>_2.txt; more _*.txt|cat\r\n::::::::::::::\r\n_1.txt\r\n::::::::::::::\r\n::::::::::::::\r\n_2.txt\r\n::::::::::::::\r\nSTDOUT\r\nSTDERR\r\n```\r\n\r\n(Above assumes an io.js that has libuv bug #224 fixed, otherwise it will output nothing, because fd 2 will be closed).\r\n\r\nAfter this patch, they are swapped, as intended:\r\n```\r\n% ./iojs fd-dup.js 1>_1.txt 2>_2.txt; more _*.txt|cat\r\n::::::::::::::\r\n_1.txt\r\n::::::::::::::\r\nSTDERR\r\n::::::::::::::\r\n_2.txt\r\n::::::::::::::\r\nSTDOUT\r\n```\r\n\r\n/to @indutny, this fixes https://github.com/joyent/libuv/issues/1084"},"comment":{"url":"https://api.github.com/repos/libuv/libuv/issues/comments/75932554","html_url":"https://github.com/libuv/libuv/pull/226#issuecomment-75932554","issue_url":"https://api.github.com/repos/libuv/libuv/issues/226","id":75932554,"user":{"login":"saghul","id":317464,"avatar_url":"https://avatars.githubusercontent.com/u/317464?v=3","gravatar_id":"","url":"https://api.github.com/users/saghul","html_url":"https://github.com/saghul","followers_url":"https://api.github.com/users/saghul/followers","following_url":"https://api.github.com/users/saghul/following{/other_user}","gists_url":"https://api.github.com/users/saghul/gists{/gist_id}","starred_url":"https://api.github.com/users/saghul/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saghul/subscriptions","organizations_url":"https://api.github.com/users/saghul/orgs","repos_url":"https://api.github.com/users/saghul/repos","events_url":"https://api.github.com/users/saghul/events{/privacy}","received_events_url":"https://api.github.com/users/saghul/received_events","type":"User","site_admin":false},"created_at":"2015-02-25T09:47:39Z","updated_at":"2015-02-25T09:47:39Z","body":"Also, a test! :-)"}}