All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] setenv/putenv errors
@ 2011-12-14 14:07 Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 1/4] compat/setenv.c: update errno when erroring out Erik Faye-Lund
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
  To: git; +Cc: peff, gitster, schwab

Here's v2 of this series. It grew a bit since the last round, as
I figured fixing the error-paths in compat/setenv.c made sense to
do while I was at it, considering how Windows (which is one of
the few likely platforms to be able to actually trigger this
issue) use it.

Erik Faye-Lund (4):
  compat/setenv.c: update errno when erroring out
  compat/setenv.c: error if name contains '='
  wrapper: supply xsetenv and xputenv
  use wrapper for unchecked setenv/putenv calls

 builtin/clone.c      |    2 +-
 builtin/commit.c     |    6 +++---
 builtin/help.c       |    4 ++--
 builtin/init-db.c    |    2 +-
 builtin/merge.c      |    4 ++--
 builtin/notes.c      |    2 +-
 builtin/remote-ext.c |    4 ++--
 builtin/revert.c     |    2 +-
 compat/setenv.c      |   10 ++++++++--
 config.c             |    2 +-
 exec_cmd.c           |    4 ++--
 git-compat-util.h    |    2 ++
 git.c                |   18 +++++++++---------
 pager.c              |    2 +-
 run-command.c        |    2 +-
 setup.c              |    6 +++---
 wrapper.c            |   14 ++++++++++++++
 17 files changed, 54 insertions(+), 32 deletions(-)

-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/4] compat/setenv.c: update errno when erroring out
  2011-12-14 14:07 [PATCH v2 0/4] setenv/putenv errors Erik Faye-Lund
@ 2011-12-14 14:07 ` Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 2/4] compat/setenv.c: error if name contains '=' Erik Faye-Lund
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
  To: git; +Cc: peff, gitster, schwab

Previously, gitsetenv didn't update errno as it should when
erroring out. Fix this.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/setenv.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/compat/setenv.c b/compat/setenv.c
index 3a22ea7..89947b7 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -6,7 +6,10 @@ int gitsetenv(const char *name, const char *value, int replace)
 	size_t namelen, valuelen;
 	char *envstr;
 
-	if (!name || !value) return -1;
+	if (!name || !value) {
+		errno = EINVAL;
+		return -1;
+	}
 	if (!replace) {
 		char *oldval = NULL;
 		oldval = getenv(name);
@@ -16,7 +19,10 @@ int gitsetenv(const char *name, const char *value, int replace)
 	namelen = strlen(name);
 	valuelen = strlen(value);
 	envstr = malloc((namelen + valuelen + 2));
-	if (!envstr) return -1;
+	if (!envstr) {
+		errno = ENOMEM;
+		return -1;
+	}
 
 	memcpy(envstr, name, namelen);
 	envstr[namelen] = '=';
-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/4] compat/setenv.c: error if name contains '='
  2011-12-14 14:07 [PATCH v2 0/4] setenv/putenv errors Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 1/4] compat/setenv.c: update errno when erroring out Erik Faye-Lund
@ 2011-12-14 14:07 ` Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 3/4] wrapper: supply xsetenv and xputenv Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls Erik Faye-Lund
  3 siblings, 0 replies; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
  To: git; +Cc: peff, gitster, schwab

According to POSIX, setenv should error out with EINVAL if it's
asked to set an environment variable whose name contains an equals
sign. Implement this detail in our compatibility-fallback.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/setenv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/compat/setenv.c b/compat/setenv.c
index 89947b7..fc1439a 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -6,7 +6,7 @@ int gitsetenv(const char *name, const char *value, int replace)
 	size_t namelen, valuelen;
 	char *envstr;
 
-	if (!name || !value) {
+	if (!name || strchr(name, '=') || !value) {
 		errno = EINVAL;
 		return -1;
 	}
-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/4] wrapper: supply xsetenv and xputenv
  2011-12-14 14:07 [PATCH v2 0/4] setenv/putenv errors Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 1/4] compat/setenv.c: update errno when erroring out Erik Faye-Lund
  2011-12-14 14:07 ` [PATCH v2 2/4] compat/setenv.c: error if name contains '=' Erik Faye-Lund
@ 2011-12-14 14:07 ` Erik Faye-Lund
  2011-12-15 17:38   ` Junio C Hamano
  2011-12-14 14:07 ` [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls Erik Faye-Lund
  3 siblings, 1 reply; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
  To: git; +Cc: peff, gitster, schwab

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 git-compat-util.h |    2 ++
 wrapper.c         |   14 ++++++++++++++
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/git-compat-util.h b/git-compat-util.h
index 77062ed..ab17d53 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -439,6 +439,8 @@ extern int xdup(int fd);
 extern FILE *xfdopen(int fd, const char *mode);
 extern int xmkstemp(char *template);
 extern int xmkstemp_mode(char *template, int mode);
+extern int xsetenv(const char *name, const char *val, int override);
+extern int xputenv(const char *string);
 extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
 extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1);
 
diff --git a/wrapper.c b/wrapper.c
index 85f09df..8d172ac 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -381,3 +381,17 @@ int remove_or_warn(unsigned int mode, const char *file)
 {
 	return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
 }
+
+int xsetenv(const char *name, const char *val, int overwrite)
+{
+	if (setenv(name, val, overwrite))
+		die_errno("setenv failed to set '%s' to '%s'", name, val);
+	return 0;
+}
+
+int xputenv(const char *string)
+{
+	if (putenv(string))
+		die_errno("putenv failed to set '%s' ", string);
+	return 0;
+}
-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls
  2011-12-14 14:07 [PATCH v2 0/4] setenv/putenv errors Erik Faye-Lund
                   ` (2 preceding siblings ...)
  2011-12-14 14:07 ` [PATCH v2 3/4] wrapper: supply xsetenv and xputenv Erik Faye-Lund
@ 2011-12-14 14:07 ` Erik Faye-Lund
  2011-12-14 18:16   ` Jeff King
  3 siblings, 1 reply; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-14 14:07 UTC (permalink / raw)
  To: git; +Cc: peff, gitster, schwab

This avoids us from accidentally dropping state, possibly leading
to unexpected behaviour.

This is especially important on Windows, where the maximum size of
the environment is 32 kB.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 builtin/clone.c      |    2 +-
 builtin/commit.c     |    6 +++---
 builtin/help.c       |    4 ++--
 builtin/init-db.c    |    2 +-
 builtin/merge.c      |    4 ++--
 builtin/notes.c      |    2 +-
 builtin/remote-ext.c |    4 ++--
 builtin/revert.c     |    2 +-
 config.c             |    2 +-
 exec_cmd.c           |    4 ++--
 git.c                |   18 +++++++++---------
 pager.c              |    2 +-
 run-command.c        |    2 +-
 setup.c              |    6 +++---
 14 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index efe8b6c..8d81c29 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -566,7 +566,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	atexit(remove_junk);
 	sigchain_push_common(remove_junk_on_signal);
 
-	setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
+	xsetenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
 
 	if (safe_create_leading_directories_const(git_dir) < 0)
 		die(_("could not create leading directories of '%s'"), git_dir);
diff --git a/builtin/commit.c b/builtin/commit.c
index e36e9ad..2b87da9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -361,13 +361,13 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 			die(_("unable to create temporary index"));
 
 		old_index_env = getenv(INDEX_ENVIRONMENT);
-		setenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
+		xsetenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
 
 		if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
 			die(_("interactive add failed"));
 
 		if (old_index_env && *old_index_env)
-			setenv(INDEX_ENVIRONMENT, old_index_env, 1);
+			xsetenv(INDEX_ENVIRONMENT, old_index_env, 1);
 		else
 			unsetenv(INDEX_ENVIRONMENT);
 
@@ -1023,7 +1023,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (edit_flag)
 		use_editor = 1;
 	if (!use_editor)
-		setenv("GIT_EDITOR", ":", 1);
+		xsetenv("GIT_EDITOR", ":", 1);
 
 	/* Sanity check options */
 	if (amend && !current_head)
diff --git a/builtin/help.c b/builtin/help.c
index 61ff798..e7dc15b 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -330,7 +330,7 @@ static void setup_man_path(void)
 	if (old_path)
 		strbuf_addstr(&new_path, old_path);
 
-	setenv("MANPATH", new_path.buf, 1);
+	xsetenv("MANPATH", new_path.buf, 1);
 
 	strbuf_release(&new_path);
 }
@@ -371,7 +371,7 @@ static void show_man_page(const char *git_cmd)
 static void show_info_page(const char *git_cmd)
 {
 	const char *page = cmd_to_page(git_cmd);
-	setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
+	xsetenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
 	execlp("info", "info", "gitman", page, (char *)NULL);
 	die("no info viewer handled the request");
 }
diff --git a/builtin/init-db.c b/builtin/init-db.c
index d07554c..21ff09e 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -537,7 +537,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	if (is_bare_repository_cfg == 1) {
 		static char git_dir[PATH_MAX+1];
 
-		setenv(GIT_DIR_ENVIRONMENT,
+		xsetenv(GIT_DIR_ENVIRONMENT,
 			getcwd(git_dir, sizeof(git_dir)), argc > 0);
 	}
 
diff --git a/builtin/merge.c b/builtin/merge.c
index a1c8534..a4ae473 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1257,7 +1257,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	strbuf_addstr(&buf, "merge");
 	for (i = 0; i < argc; i++)
 		strbuf_addf(&buf, " %s", argv[i]);
-	setenv("GIT_REFLOG_ACTION", buf.buf, 0);
+	xsetenv("GIT_REFLOG_ACTION", buf.buf, 0);
 	strbuf_reset(&buf);
 
 	for (i = 0; i < argc; i++) {
@@ -1267,7 +1267,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		remotes = &commit_list_insert(commit, remotes)->next;
 		strbuf_addf(&buf, "GITHEAD_%s",
 			    sha1_to_hex(commit->object.sha1));
-		setenv(buf.buf, argv[i], 1);
+		xsetenv(buf.buf, argv[i], 1);
 		strbuf_reset(&buf);
 		if (merge_remote_util(commit) &&
 		    merge_remote_util(commit)->obj &&
diff --git a/builtin/notes.c b/builtin/notes.c
index 10b8bc7..7b53c69 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -1076,7 +1076,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
 		struct strbuf sb = STRBUF_INIT;
 		strbuf_addstr(&sb, override_notes_ref);
 		expand_notes_ref(&sb);
-		setenv("GIT_NOTES_REF", sb.buf, 1);
+		xsetenv("GIT_NOTES_REF", sb.buf, 1);
 		strbuf_release(&sb);
 	}
 
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index 692c834..0b2169a 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -38,8 +38,8 @@ static char *strip_escapes(const char *str, const char *service,
 		psoff = 4;
 
 	/* Pass the service to command. */
-	setenv("GIT_EXT_SERVICE", service, 1);
-	setenv("GIT_EXT_SERVICE_NOPREFIX", service + psoff, 1);
+	xsetenv("GIT_EXT_SERVICE", service, 1);
+	xsetenv("GIT_EXT_SERVICE_NOPREFIX", service + psoff, 1);
 
 	/* Scan the length of argument. */
 	while (str[rpos] && (escape || str[rpos] != ' ')) {
diff --git a/builtin/revert.c b/builtin/revert.c
index 1ea525c..955a99f 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -1007,7 +1007,7 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
 	struct commit_list *cur;
 	int res;
 
-	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
+	xsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit));
diff --git a/config.c b/config.c
index 5ea101f..f461a62 100644
--- a/config.c
+++ b/config.c
@@ -43,7 +43,7 @@ void git_config_push_parameter(const char *text)
 		strbuf_addch(&env, ' ');
 	}
 	sq_quote_buf(&env, text);
-	setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
+	xsetenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
 	strbuf_release(&env);
 }
 
diff --git a/exec_cmd.c b/exec_cmd.c
index 171e841..a5a92dd 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -63,7 +63,7 @@ void git_set_argv_exec_path(const char *exec_path)
 	/*
 	 * Propagate this setting to external programs.
 	 */
-	setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
+	xsetenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
 }
 
 
@@ -108,7 +108,7 @@ void setup_path(void)
 	else
 		strbuf_addstr(&new_path, _PATH_DEFPATH);
 
-	setenv("PATH", new_path.buf, 1);
+	xsetenv("PATH", new_path.buf, 1);
 
 	strbuf_release(&new_path);
 }
diff --git a/git.c b/git.c
index 8e34903..cb80de2 100644
--- a/git.c
+++ b/git.c
@@ -54,7 +54,7 @@ int check_pager_config(const char *cmd)
 static void commit_pager_choice(void) {
 	switch (use_pager) {
 	case 0:
-		setenv("GIT_PAGER", "cat", 1);
+		xsetenv("GIT_PAGER", "cat", 1);
 		break;
 	case 1:
 		setup_pager();
@@ -109,7 +109,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--no-replace-objects")) {
 			read_replace_refs = 0;
-			setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
+			xsetenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
@@ -117,13 +117,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No directory given for --git-dir.\n" );
 				usage(git_usage_string);
 			}
-			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
+			xsetenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, "--git-dir=")) {
-			setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
+			xsetenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--namespace")) {
@@ -131,13 +131,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No namespace given for --namespace.\n" );
 				usage(git_usage_string);
 			}
-			setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
+			xsetenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, "--namespace=")) {
-			setenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
+			xsetenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
@@ -145,19 +145,19 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No directory given for --work-tree.\n" );
 				usage(git_usage_string);
 			}
-			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
+			xsetenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, "--work-tree=")) {
-			setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
+			xsetenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--bare")) {
 			static char git_dir[PATH_MAX+1];
 			is_bare_repository_cfg = 1;
-			setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
+			xsetenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "-c")) {
diff --git a/pager.c b/pager.c
index 975955b..d3a1299 100644
--- a/pager.c
+++ b/pager.c
@@ -76,7 +76,7 @@ void setup_pager(void)
 	if (!pager)
 		return;
 
-	setenv("GIT_PAGER_IN_USE", "true", 1);
+	xsetenv("GIT_PAGER_IN_USE", "true", 1);
 
 	/* spawn the pager */
 	pager_argv[0] = pager;
diff --git a/run-command.c b/run-command.c
index 1c51043..37abbde 100644
--- a/run-command.c
+++ b/run-command.c
@@ -258,7 +258,7 @@ fail_pipe:
 		if (cmd->env) {
 			for (; *cmd->env; cmd->env++) {
 				if (strchr(*cmd->env, '='))
-					putenv((char *)*cmd->env);
+					xputenv((char *)*cmd->env);
 				else
 					unsetenv(*cmd->env);
 			}
diff --git a/setup.c b/setup.c
index 61c22e6..06f38d0 100644
--- a/setup.c
+++ b/setup.c
@@ -309,7 +309,7 @@ void setup_work_tree(void)
 	 * if $GIT_WORK_TREE is set relative
 	 */
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
-		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
+		xsetenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
 	set_git_dir(relative_path(git_dir, work_tree));
 	initialized = 1;
@@ -683,9 +683,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
 	prefix = setup_git_directory_gently_1(nongit_ok);
 	if (prefix)
-		setenv("GIT_PREFIX", prefix, 1);
+		xsetenv("GIT_PREFIX", prefix, 1);
 	else
-		setenv("GIT_PREFIX", "", 1);
+		xsetenv("GIT_PREFIX", "", 1);
 
 	if (startup_info) {
 		startup_info->have_repository = !nongit_ok || !*nongit_ok;
-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls
  2011-12-14 14:07 ` [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls Erik Faye-Lund
@ 2011-12-14 18:16   ` Jeff King
  2011-12-15 18:04     ` Erik Faye-Lund
  0 siblings, 1 reply; 9+ messages in thread
From: Jeff King @ 2011-12-14 18:16 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, gitster, schwab

On Wed, Dec 14, 2011 at 03:07:11PM +0100, Erik Faye-Lund wrote:

> This avoids us from accidentally dropping state, possibly leading
> to unexpected behaviour.

I do think this is fine in a "be extra cautious" kind of way.

> This is especially important on Windows, where the maximum size of
> the environment is 32 kB.

But does your patch actually detect that? As Andreas pointed out, these
limits don't typically come into play at setenv time. Instead, the
environment is allocated on the heap, and then the result is passed to
exec/spawn, which will fail.

So your patch is really detecting a failure to malloc, not an overflow
of the environment size, and Windows is just as (un)likely to run out of
heap as any other platform.

You can check how your platform behaves by applying this patch:

diff --git a/git.c b/git.c
index f10e434..57f6b12 100644
--- a/git.c
+++ b/git.c
@@ -223,6 +223,16 @@ static int handle_alias(int *argcp, const char ***argv)
 				alias_argv[i] = (*argv)[i];
 			alias_argv[argc] = NULL;
 
+			/* make gigantic environment */
+			{
+				int len = 256 * 1024;
+				char *buf = xmalloc(len);
+				memset(buf, 'z', len);
+				buf[len-1] = '\0';
+				if (setenv("FOO", buf, 1))
+					die("setenv failed");
+			}
+
 			ret = run_command_v_opt(alias_argv, RUN_USING_SHELL);
 			if (ret >= 0)   /* normal exit */
 				exit(ret);

and then running:

  git -c alias.foo='!echo ok' foo

which yields:

  fatal: cannot exec 'echo ok': Argument list too long

on Linux.

-Peff

PS I tried to come up with an invocation of git that would demonstrate
   this, but it turns out it's really hard. The contents of environment
   variables we set are either constants, come from the environment (so
   they can't be too big already!), or come from filesystem paths. So
   it's possible to overflow now, but you have to have a nearly-full
   environment in the first place, and then have a long path that tips
   it over the limit.

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/4] wrapper: supply xsetenv and xputenv
  2011-12-14 14:07 ` [PATCH v2 3/4] wrapper: supply xsetenv and xputenv Erik Faye-Lund
@ 2011-12-15 17:38   ` Junio C Hamano
  2011-12-15 18:25     ` Erik Faye-Lund
  0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2011-12-15 17:38 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, peff, schwab

Erik Faye-Lund <kusmabite@gmail.com> writes:

> +extern int xsetenv(const char *name, const char *val, int override);
> +extern int xputenv(const char *string);

Actually, putenv(3) takes "char *string".

I adjusted 3 & 4 locally before queuing, so there is no need for resend,
and judging from the later part of the discussion, it seems that it may be
better to use only the first two patches from this series after all.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls
  2011-12-14 18:16   ` Jeff King
@ 2011-12-15 18:04     ` Erik Faye-Lund
  0 siblings, 0 replies; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-15 18:04 UTC (permalink / raw)
  To: Jeff King; +Cc: git, gitster, schwab

On Wed, Dec 14, 2011 at 7:16 PM, Jeff King <peff@peff.net> wrote:
> On Wed, Dec 14, 2011 at 03:07:11PM +0100, Erik Faye-Lund wrote:
>
>> This avoids us from accidentally dropping state, possibly leading
>> to unexpected behaviour.
>
> I do think this is fine in a "be extra cautious" kind of way.
>
>> This is especially important on Windows, where the maximum size of
>> the environment is 32 kB.
>
> But does your patch actually detect that? As Andreas pointed out, these
> limits don't typically come into play at setenv time. Instead, the
> environment is allocated on the heap, and then the result is passed to
> exec/spawn, which will fail.
>
> So your patch is really detecting a failure to malloc, not an overflow
> of the environment size, and Windows is just as (un)likely to run out of
> heap as any other platform.
>

You are right; I just assumed that our setenv was implemented on top
of SetEnvironmentVariable, which does impose max-limits on setting (if
I read the documentation correctly):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686206(v=vs.85).aspx

But we don't. We have mingw_setenv, which simply modifies environ.

> You can check how your platform behaves by applying this patch:
>
> diff --git a/git.c b/git.c
> index f10e434..57f6b12 100644
> --- a/git.c
> +++ b/git.c
> @@ -223,6 +223,16 @@ static int handle_alias(int *argcp, const char ***argv)
>                                alias_argv[i] = (*argv)[i];
>                        alias_argv[argc] = NULL;
>
> +                       /* make gigantic environment */
> +                       {
> +                               int len = 256 * 1024;
> +                               char *buf = xmalloc(len);
> +                               memset(buf, 'z', len);
> +                               buf[len-1] = '\0';
> +                               if (setenv("FOO", buf, 1))
> +                                       die("setenv failed");
> +                       }
> +
>                        ret = run_command_v_opt(alias_argv, RUN_USING_SHELL);
>                        if (ret >= 0)   /* normal exit */
>                                exit(ret);
>
> and then running:
>
>  git -c alias.foo='!echo ok' foo
>
> which yields:
>
>  fatal: cannot exec 'echo ok': Argument list too long
>
> on Linux.
>

Yeah, but I'm getting:
$ git -c alias.foo='!echo ok' foo
ok

Which is strange to me.

But if I do:
$ git -c alias.foo='!echo $FOO' foo

it does echo a bunch of 'z's. And we get the expected amount:
$ git -c alias.foo='!echo $FOO' foo | wc -c
 262144

This strikes me as very strange, because we end up calling the ANSI
version of CreateProcess with an environment-block beyond 32767 chars,
which MSDN says should fail:

"The ANSI version of this function, CreateProcessA fails if the total
size of the environment block for the process exceeds 32,767
characters."

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx

Oh well, this is strange behavior in a good way; I'm not going to complain :P

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/4] wrapper: supply xsetenv and xputenv
  2011-12-15 17:38   ` Junio C Hamano
@ 2011-12-15 18:25     ` Erik Faye-Lund
  0 siblings, 0 replies; 9+ messages in thread
From: Erik Faye-Lund @ 2011-12-15 18:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, peff, schwab

On Thu, Dec 15, 2011 at 6:38 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Erik Faye-Lund <kusmabite@gmail.com> writes:
>
>> +extern int xsetenv(const char *name, const char *val, int override);
>> +extern int xputenv(const char *string);
>
> Actually, putenv(3) takes "char *string".

Ah, thanks for spotting.

> I adjusted 3 & 4 locally before queuing, so there is no need for resend,
> and judging from the later part of the discussion, it seems that it may be
> better to use only the first two patches from this series after all.

Yeah, I agree; patch 1 and 2 are the only ones that makes sense.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-12-15 18:26 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-14 14:07 [PATCH v2 0/4] setenv/putenv errors Erik Faye-Lund
2011-12-14 14:07 ` [PATCH v2 1/4] compat/setenv.c: update errno when erroring out Erik Faye-Lund
2011-12-14 14:07 ` [PATCH v2 2/4] compat/setenv.c: error if name contains '=' Erik Faye-Lund
2011-12-14 14:07 ` [PATCH v2 3/4] wrapper: supply xsetenv and xputenv Erik Faye-Lund
2011-12-15 17:38   ` Junio C Hamano
2011-12-15 18:25     ` Erik Faye-Lund
2011-12-14 14:07 ` [PATCH v2 4/4] use wrapper for unchecked setenv/putenv calls Erik Faye-Lund
2011-12-14 18:16   ` Jeff King
2011-12-15 18:04     ` Erik Faye-Lund

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.