Skip to content

Commit 64472d1

Browse files
bk2204gitster
authored andcommitted
http-push: ensure unforced pushes fail when data would be lost
When we push using the DAV-based protocol, the client is the one that performs the ref updates and therefore makes the checks to see whether an unforced push should be allowed. We make this check by determining if either (a) we lack the object file for the old value of the ref or (b) the new value of the ref is not newer than the old value, and in either case, reject the push. However, the ref_newer function, which performs this latter check, has an odd behavior due to the reuse of certain object flags. Specifically, it will incorrectly return false in its first invocation and then correctly return true on a subsequent invocation. This occurs because the object flags used by http-push.c are the same as those used by commit-reach.c, which implements ref_newer, and one piece of code misinterprets the flags set by the other. Note that this does not occur in all cases. For example, if the example used in the tests is changed to use one repository instead of two and rewind the head to add a commit, the test passes and we correctly reject the push. However, the example provided does trigger this behavior, and the code has been broken in this way since at least Git 2.0.0. To solve this problem, let's move the two sets of object flags so that they don't overlap, since we're clearly using them at the same time. The new set should not conflict with other usage because other users are either builtin code (which is not compiled into git http-push) or upload-pack (which we similarly do not use here). Reported-by: Michael Ward <[email protected]> Signed-off-by: René Scharfe <[email protected]> Signed-off-by: brian m. carlson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent af6b65d commit 64472d1

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

http-push.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ enum XML_Status {
7070
#define LOCK_REFRESH 30
7171

7272
/* Remember to update object flag allocation in object.h */
73-
#define LOCAL (1u<<16)
74-
#define REMOTE (1u<<17)
75-
#define FETCHING (1u<<18)
76-
#define PUSHING (1u<<19)
73+
#define LOCAL (1u<<11)
74+
#define REMOTE (1u<<12)
75+
#define FETCHING (1u<<13)
76+
#define PUSHING (1u<<14)
7777

7878
/* We allow "recursive" symbolic refs. Only within reason, though */
7979
#define MAXDEPTH 5

object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct object_array {
6767
* builtin/blame.c: 12-13
6868
* bisect.c: 16
6969
* bundle.c: 16
70-
* http-push.c: 16-----19
70+
* http-push.c: 11-----14
7171
* commit-graph.c: 15
7272
* commit-reach.c: 16-----19
7373
* sha1-name.c: 20

t/t5540-http-push-webdav.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ test_expect_success 'create and delete remote branch' '
126126
test_must_fail git show-ref --verify refs/remotes/origin/dev
127127
'
128128

129+
test_expect_success 'non-force push fails if not up to date' '
130+
git init --bare "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_conflict.git &&
131+
git -C "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo_conflict.git update-server-info &&
132+
git clone $HTTPD_URL/dumb/test_repo_conflict.git "$ROOT_PATH"/c1 &&
133+
git clone $HTTPD_URL/dumb/test_repo_conflict.git "$ROOT_PATH"/c2 &&
134+
test_commit -C "$ROOT_PATH/c1" path1 &&
135+
git -C "$ROOT_PATH/c1" push origin HEAD &&
136+
git -C "$ROOT_PATH/c2" pull &&
137+
test_commit -C "$ROOT_PATH/c1" path2 &&
138+
git -C "$ROOT_PATH/c1" push origin HEAD &&
139+
test_commit -C "$ROOT_PATH/c2" path3 &&
140+
git -C "$ROOT_PATH/c1" log --graph --all &&
141+
git -C "$ROOT_PATH/c2" log --graph --all &&
142+
test_must_fail git -C "$ROOT_PATH/c2" push origin HEAD
143+
'
144+
129145
test_expect_success 'MKCOL sends directory names with trailing slashes' '
130146
131147
! grep "\"MKCOL.*[^/] HTTP/[^ ]*\"" < "$HTTPD_ROOT_PATH"/access.log

0 commit comments

Comments
 (0)