Merge branch 'dt/refs-check-refname-component-optim'
* dt/refs-check-refname-component-optim: refs.c: optimize check_refname_component()
This commit is contained in:
commit
ae7dd1a492
67
refs.c
67
refs.c
@ -6,8 +6,29 @@
|
|||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure "ref" is something reasonable to have under ".git/refs/";
|
* How to handle various characters in refnames:
|
||||||
* We do not like it if:
|
* 0: An acceptable character for refs
|
||||||
|
* 1: End-of-component
|
||||||
|
* 2: ., look for a preceding . to reject .. in refs
|
||||||
|
* 3: {, look for a preceding @ to reject @{ in refs
|
||||||
|
* 4: A bad character: ASCII control characters, "~", "^", ":" or SP
|
||||||
|
*/
|
||||||
|
static unsigned char refname_disposition[256] = {
|
||||||
|
1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 1,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to read one refname component from the front of refname.
|
||||||
|
* Return the length of the component found, or -1 if the component is
|
||||||
|
* not legal. It is legal if it is something reasonable to have under
|
||||||
|
* ".git/refs/"; We do not like it if:
|
||||||
*
|
*
|
||||||
* - any path component of it begins with ".", or
|
* - any path component of it begins with ".", or
|
||||||
* - it has double dots "..", or
|
* - it has double dots "..", or
|
||||||
@ -16,41 +37,31 @@
|
|||||||
* - it ends with ".lock"
|
* - it ends with ".lock"
|
||||||
* - it contains a "\" (backslash)
|
* - it contains a "\" (backslash)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Return true iff ch is not allowed in reference names. */
|
|
||||||
static inline int bad_ref_char(int ch)
|
|
||||||
{
|
|
||||||
if (((unsigned) ch) <= ' ' || ch == 0x7f ||
|
|
||||||
ch == '~' || ch == '^' || ch == ':' || ch == '\\')
|
|
||||||
return 1;
|
|
||||||
/* 2.13 Pattern Matching Notation */
|
|
||||||
if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to read one refname component from the front of refname. Return
|
|
||||||
* the length of the component found, or -1 if the component is not
|
|
||||||
* legal.
|
|
||||||
*/
|
|
||||||
static int check_refname_component(const char *refname, int flags)
|
static int check_refname_component(const char *refname, int flags)
|
||||||
{
|
{
|
||||||
const char *cp;
|
const char *cp;
|
||||||
char last = '\0';
|
char last = '\0';
|
||||||
|
|
||||||
for (cp = refname; ; cp++) {
|
for (cp = refname; ; cp++) {
|
||||||
char ch = *cp;
|
int ch = *cp & 255;
|
||||||
if (ch == '\0' || ch == '/')
|
unsigned char disp = refname_disposition[ch];
|
||||||
|
switch (disp) {
|
||||||
|
case 1:
|
||||||
|
goto out;
|
||||||
|
case 2:
|
||||||
|
if (last == '.')
|
||||||
|
return -1; /* Refname contains "..". */
|
||||||
break;
|
break;
|
||||||
if (bad_ref_char(ch))
|
case 3:
|
||||||
return -1; /* Illegal character in refname. */
|
if (last == '@')
|
||||||
if (last == '.' && ch == '.')
|
return -1; /* Refname contains "@{". */
|
||||||
return -1; /* Refname contains "..". */
|
break;
|
||||||
if (last == '@' && ch == '{')
|
case 4:
|
||||||
return -1; /* Refname contains "@{". */
|
return -1;
|
||||||
|
}
|
||||||
last = ch;
|
last = ch;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
if (cp == refname)
|
if (cp == refname)
|
||||||
return 0; /* Component has zero length. */
|
return 0; /* Component has zero length. */
|
||||||
if (refname[0] == '.') {
|
if (refname[0] == '.') {
|
||||||
|
@ -5,7 +5,6 @@ test_description='refspec parsing'
|
|||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_refspec () {
|
test_refspec () {
|
||||||
|
|
||||||
kind=$1 refspec=$2 expect=$3
|
kind=$1 refspec=$2 expect=$3
|
||||||
git config remote.frotz.url "." &&
|
git config remote.frotz.url "." &&
|
||||||
git config --remove-section remote.frotz &&
|
git config --remove-section remote.frotz &&
|
||||||
@ -84,4 +83,9 @@ test_refspec push 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
|
|||||||
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*'
|
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*'
|
||||||
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*'
|
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*'
|
||||||
|
|
||||||
|
good=$(printf '\303\204')
|
||||||
|
test_refspec fetch "refs/heads/${good}"
|
||||||
|
bad=$(printf '\011tab')
|
||||||
|
test_refspec fetch "refs/heads/${bad}" invalid
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user