branch: segfault fixes and validation
branch_get() can return NULL (so far on detached HEAD only) but some code paths in builtin/branch.c cannot deal with that and cause segfaults. While at there, make sure to bail out when the user gives 2 or more branches with --set-upstream-to or --unset-upstream, where only the first branch is processed and the rest silently dropped. Reported-by: Per Cederqvist <cederp@opera.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									d040350813
								
							
						
					
					
						commit
						8efb8899cf
					
				|  | @ -889,6 +889,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix) | |||
| 	} else if (new_upstream) { | ||||
| 		struct branch *branch = branch_get(argv[0]); | ||||
|  | ||||
| 		if (argc > 1) | ||||
| 			die(_("too many branches to set new upstream")); | ||||
|  | ||||
| 		if (!branch) { | ||||
| 			if (!argc || !strcmp(argv[0], "HEAD")) | ||||
| 				die(_("could not set upstream of HEAD to %s when " | ||||
| 				      "it does not point to any branch."), | ||||
| 				    new_upstream); | ||||
| 			die(_("no such branch '%s'"), argv[0]); | ||||
| 		} | ||||
|  | ||||
| 		if (!ref_exists(branch->refname)) | ||||
| 			die(_("branch '%s' does not exist"), branch->name); | ||||
|  | ||||
|  | @ -901,6 +912,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix) | |||
| 		struct branch *branch = branch_get(argv[0]); | ||||
| 		struct strbuf buf = STRBUF_INIT; | ||||
|  | ||||
| 		if (argc > 1) | ||||
| 			die(_("too many branches to unset upstream")); | ||||
|  | ||||
| 		if (!branch) { | ||||
| 			if (!argc || !strcmp(argv[0], "HEAD")) | ||||
| 				die(_("could not unset upstream of HEAD when " | ||||
| 				      "it does not point to any branch.")); | ||||
| 			die(_("no such branch '%s'"), argv[0]); | ||||
| 		} | ||||
|  | ||||
| 		if (!branch_has_merge_config(branch)) { | ||||
| 			die(_("Branch '%s' has no upstream information"), branch->name); | ||||
| 		} | ||||
|  | @ -916,6 +937,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix) | |||
| 		int branch_existed = 0, remote_tracking = 0; | ||||
| 		struct strbuf buf = STRBUF_INIT; | ||||
|  | ||||
| 		if (!strcmp(argv[0], "HEAD")) | ||||
| 			die(_("it does not make sense to create 'HEAD' manually")); | ||||
|  | ||||
| 		if (!branch) | ||||
| 			die(_("no such branch '%s'"), argv[0]); | ||||
|  | ||||
| 		if (kinds != REF_LOCAL_BRANCH) | ||||
| 			die(_("-a and -r options to 'git branch' do not make sense with a branch name")); | ||||
|  | ||||
|  |  | |||
|  | @ -42,6 +42,10 @@ test_expect_success \ | |||
|     'git branch a/b/c should create a branch' \ | ||||
|     'git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c' | ||||
|  | ||||
| test_expect_success \ | ||||
|     'git branch HEAD should fail' \ | ||||
|     'test_must_fail git branch HEAD' | ||||
|  | ||||
| cat >expect <<EOF | ||||
| $_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000	branch: Created from master | ||||
| EOF | ||||
|  | @ -388,6 +392,14 @@ test_expect_success \ | |||
|     'git tag foobar && | ||||
|      test_must_fail git branch --track my11 foobar' | ||||
|  | ||||
| test_expect_success '--set-upstream-to fails on multiple branches' \ | ||||
|     'test_must_fail git branch --set-upstream-to master a b c' | ||||
|  | ||||
| test_expect_success '--set-upstream-to fails on detached HEAD' \ | ||||
|     'git checkout HEAD^{} && | ||||
|      test_must_fail git branch --set-upstream-to master && | ||||
|      git checkout -' | ||||
|  | ||||
| test_expect_success 'use --set-upstream-to modify HEAD' \ | ||||
|     'test_config branch.master.remote foo && | ||||
|      test_config branch.master.merge foo && | ||||
|  | @ -417,6 +429,15 @@ test_expect_success 'test --unset-upstream on HEAD' \ | |||
|      test_must_fail git branch --unset-upstream | ||||
| ' | ||||
|  | ||||
| test_expect_success '--unset-upstream should fail on multiple branches' \ | ||||
|     'test_must_fail git branch --unset-upstream a b c' | ||||
|  | ||||
| test_expect_success '--unset-upstream should fail on detached HEAD' \ | ||||
|     'git checkout HEAD^{} && | ||||
|      test_must_fail git branch --unset-upstream && | ||||
|      git checkout - | ||||
| ' | ||||
|  | ||||
| test_expect_success 'test --unset-upstream on a particular branch' \ | ||||
|     'git branch my15 | ||||
|      git branch --set-upstream-to master my14 && | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy