Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
ce8803a2
Unverified
Commit
ce8803a2
authored
Oct 05, 2018
by
Patrick Steinhardt
Committed by
GitHub
Oct 05, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4836 from pks-t/pks/smart-packets
Smart packet security fixes
parents
84d6f439
1bc5b05c
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
465 additions
and
109 deletions
+465
-109
src/transports/smart.h
+3
-3
src/transports/smart_pkt.c
+117
-101
src/transports/smart_protocol.c
+5
-5
tests/transports/smart/packet.c
+340
-0
No files found.
src/transports/smart.h
View file @
ce8803a2
...
@@ -90,7 +90,7 @@ typedef struct {
...
@@ -90,7 +90,7 @@ typedef struct {
typedef
struct
{
typedef
struct
{
git_pkt_type
type
;
git_pkt_type
type
;
in
t
len
;
size_
t
len
;
char
data
[
GIT_FLEX_ARRAY
];
char
data
[
GIT_FLEX_ARRAY
];
}
git_pkt_data
;
}
git_pkt_data
;
...
@@ -98,7 +98,7 @@ typedef git_pkt_data git_pkt_progress;
...
@@ -98,7 +98,7 @@ typedef git_pkt_data git_pkt_progress;
typedef
struct
{
typedef
struct
{
git_pkt_type
type
;
git_pkt_type
type
;
in
t
len
;
size_
t
len
;
char
error
[
GIT_FLEX_ARRAY
];
char
error
[
GIT_FLEX_ARRAY
];
}
git_pkt_err
;
}
git_pkt_err
;
...
@@ -188,7 +188,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
...
@@ -188,7 +188,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
int
git_smart__update_heads
(
transport_smart
*
t
,
git_vector
*
symrefs
);
int
git_smart__update_heads
(
transport_smart
*
t
,
git_vector
*
symrefs
);
/* smart_pkt.c */
/* smart_pkt.c */
int
git_pkt_parse_line
(
git_pkt
**
head
,
const
char
*
line
,
const
char
**
out
,
size_t
len
);
int
git_pkt_parse_line
(
git_pkt
**
head
,
const
char
*
*
endptr
,
const
char
*
line
,
size_t
line
len
);
int
git_pkt_buffer_flush
(
git_buf
*
buf
);
int
git_pkt_buffer_flush
(
git_buf
*
buf
);
int
git_pkt_send_flush
(
GIT_SOCKET
s
);
int
git_pkt_send_flush
(
GIT_SOCKET
s
);
int
git_pkt_buffer_done
(
git_buf
*
buf
);
int
git_pkt_buffer_done
(
git_buf
*
buf
);
...
...
src/transports/smart_pkt.c
View file @
ce8803a2
...
@@ -43,34 +43,43 @@ static int flush_pkt(git_pkt **out)
...
@@ -43,34 +43,43 @@ static int flush_pkt(git_pkt **out)
static
int
ack_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
static
int
ack_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
{
{
git_pkt_ack
*
pkt
;
git_pkt_ack
*
pkt
;
GIT_UNUSED
(
line
);
GIT_UNUSED
(
len
);
pkt
=
git__calloc
(
1
,
sizeof
(
git_pkt_ack
));
pkt
=
git__calloc
(
1
,
sizeof
(
git_pkt_ack
));
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_ACK
;
pkt
->
type
=
GIT_PKT_ACK
;
line
+=
3
;
len
-=
3
;
if
(
len
>=
GIT_OID_HEXSZ
)
{
if
(
git__prefixncmp
(
line
,
len
,
"ACK "
))
git_oid_fromstr
(
&
pkt
->
oid
,
line
+
1
);
goto
out_err
;
line
+=
GIT_OID_HEXSZ
+
1
;
line
+=
4
;
len
-=
GIT_OID_HEXSZ
+
1
;
len
-=
4
;
}
if
(
len
<
GIT_OID_HEXSZ
||
git_oid_fromstr
(
&
pkt
->
oid
,
line
)
<
0
)
goto
out_err
;
line
+=
GIT_OID_HEXSZ
;
len
-=
GIT_OID_HEXSZ
;
if
(
len
>=
7
)
{
if
(
len
&&
line
[
0
]
==
' '
)
{
if
(
!
git__prefixcmp
(
line
+
1
,
"continue"
))
line
++
;
len
--
;
if
(
!
git__prefixncmp
(
line
,
len
,
"continue"
))
pkt
->
status
=
GIT_ACK_CONTINUE
;
pkt
->
status
=
GIT_ACK_CONTINUE
;
if
(
!
git__prefixcmp
(
line
+
1
,
"common"
))
else
if
(
!
git__prefixncmp
(
line
,
len
,
"common"
))
pkt
->
status
=
GIT_ACK_COMMON
;
pkt
->
status
=
GIT_ACK_COMMON
;
if
(
!
git__prefixcmp
(
line
+
1
,
"ready"
))
else
if
(
!
git__prefixncmp
(
line
,
len
,
"ready"
))
pkt
->
status
=
GIT_ACK_READY
;
pkt
->
status
=
GIT_ACK_READY
;
else
goto
out_err
;
}
}
*
out
=
(
git_pkt
*
)
pkt
;
*
out
=
(
git_pkt
*
)
pkt
;
return
0
;
return
0
;
out_err:
giterr_set
(
GITERR_NET
,
"error parsing ACK pkt-line"
);
git__free
(
pkt
);
return
-
1
;
}
}
static
int
nak_pkt
(
git_pkt
**
out
)
static
int
nak_pkt
(
git_pkt
**
out
)
...
@@ -107,10 +116,12 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -107,10 +116,12 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
static
int
err_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
static
int
err_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
{
{
git_pkt_err
*
pkt
;
git_pkt_err
*
pkt
=
NULL
;
size_t
alloclen
;
size_t
alloclen
;
/* Remove "ERR " from the line */
/* Remove "ERR " from the line */
if
(
git__prefixncmp
(
line
,
len
,
"ERR "
))
goto
out_err
;
line
+=
4
;
line
+=
4
;
len
-=
4
;
len
-=
4
;
...
@@ -118,15 +129,20 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -118,15 +129,20 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC_ADD
(
&
alloclen
,
alloclen
,
1
);
GITERR_CHECK_ALLOC_ADD
(
&
alloclen
,
alloclen
,
1
);
pkt
=
git__malloc
(
alloclen
);
pkt
=
git__malloc
(
alloclen
);
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_ERR
;
pkt
->
type
=
GIT_PKT_ERR
;
pkt
->
len
=
(
int
)
len
;
pkt
->
len
=
len
;
memcpy
(
pkt
->
error
,
line
,
len
);
memcpy
(
pkt
->
error
,
line
,
len
);
pkt
->
error
[
len
]
=
'\0'
;
pkt
->
error
[
len
]
=
'\0'
;
*
out
=
(
git_pkt
*
)
pkt
;
*
out
=
(
git_pkt
*
)
pkt
;
return
0
;
return
0
;
out_err:
giterr_set
(
GITERR_NET
,
"error parsing ERR pkt-line"
);
git__free
(
pkt
);
return
-
1
;
}
}
static
int
data_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
static
int
data_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
...
@@ -142,7 +158,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -142,7 +158,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_DATA
;
pkt
->
type
=
GIT_PKT_DATA
;
pkt
->
len
=
(
int
)
len
;
pkt
->
len
=
len
;
memcpy
(
pkt
->
data
,
line
,
len
);
memcpy
(
pkt
->
data
,
line
,
len
);
*
out
=
(
git_pkt
*
)
pkt
;
*
out
=
(
git_pkt
*
)
pkt
;
...
@@ -163,7 +179,7 @@ static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -163,7 +179,7 @@ static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_PROGRESS
;
pkt
->
type
=
GIT_PKT_PROGRESS
;
pkt
->
len
=
(
int
)
len
;
pkt
->
len
=
len
;
memcpy
(
pkt
->
data
,
line
,
len
);
memcpy
(
pkt
->
data
,
line
,
len
);
*
out
=
(
git_pkt
*
)
pkt
;
*
out
=
(
git_pkt
*
)
pkt
;
...
@@ -199,33 +215,25 @@ static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -199,33 +215,25 @@ static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
*/
*/
static
int
ref_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
static
int
ref_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
{
{
int
error
;
git_pkt_ref
*
pkt
;
git_pkt_ref
*
pkt
;
size_t
alloclen
;
size_t
alloclen
;
if
(
len
<
GIT_OID_HEXSZ
+
1
)
{
pkt
=
git__calloc
(
1
,
sizeof
(
git_pkt_ref
));
giterr_set
(
GITERR_NET
,
"error parsing pkt-line"
);
return
-
1
;
}
pkt
=
git__malloc
(
sizeof
(
git_pkt_ref
));
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
memset
(
pkt
,
0x0
,
sizeof
(
git_pkt_ref
));
pkt
->
type
=
GIT_PKT_REF
;
pkt
->
type
=
GIT_PKT_REF
;
if
((
error
=
git_oid_fromstr
(
&
pkt
->
head
.
oid
,
line
))
<
0
)
goto
error_out
;
/* Check for a bit of consistency */
if
(
line
[
GIT_OID_HEXSZ
]
!=
' '
)
{
giterr_set
(
GITERR_NET
,
"error parsing pkt-line"
);
error
=
-
1
;
goto
error_out
;
}
/* Jump from the name */
if
(
len
<
GIT_OID_HEXSZ
||
git_oid_fromstr
(
&
pkt
->
head
.
oid
,
line
)
<
0
)
line
+=
GIT_OID_HEXSZ
+
1
;
goto
out_err
;
len
-=
(
GIT_OID_HEXSZ
+
1
);
line
+=
GIT_OID_HEXSZ
;
len
-=
GIT_OID_HEXSZ
;
if
(
git__prefixncmp
(
line
,
len
,
" "
))
goto
out_err
;
line
++
;
len
--
;
if
(
!
len
)
goto
out_err
;
if
(
line
[
len
-
1
]
==
'\n'
)
if
(
line
[
len
-
1
]
==
'\n'
)
--
len
;
--
len
;
...
@@ -237,36 +245,36 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -237,36 +245,36 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
memcpy
(
pkt
->
head
.
name
,
line
,
len
);
memcpy
(
pkt
->
head
.
name
,
line
,
len
);
pkt
->
head
.
name
[
len
]
=
'\0'
;
pkt
->
head
.
name
[
len
]
=
'\0'
;
if
(
strlen
(
pkt
->
head
.
name
)
<
len
)
{
if
(
strlen
(
pkt
->
head
.
name
)
<
len
)
pkt
->
capabilities
=
strchr
(
pkt
->
head
.
name
,
'\0'
)
+
1
;
pkt
->
capabilities
=
strchr
(
pkt
->
head
.
name
,
'\0'
)
+
1
;
}
*
out
=
(
git_pkt
*
)
pkt
;
*
out
=
(
git_pkt
*
)
pkt
;
return
0
;
return
0
;
error_out:
out_err:
giterr_set
(
GITERR_NET
,
"error parsing REF pkt-line"
);
if
(
pkt
)
git__free
(
pkt
->
head
.
name
);
git__free
(
pkt
);
git__free
(
pkt
);
return
error
;
return
-
1
;
}
}
static
int
ok_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
static
int
ok_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
{
{
git_pkt_ok
*
pkt
;
git_pkt_ok
*
pkt
;
const
char
*
ptr
;
size_t
alloc_len
;
size_t
alloc_len
;
pkt
=
git__malloc
(
sizeof
(
*
pkt
));
pkt
=
git__malloc
(
sizeof
(
*
pkt
));
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_OK
;
pkt
->
type
=
GIT_PKT_OK
;
line
+=
3
;
/* skip "ok " */
if
(
git__prefixncmp
(
line
,
len
,
"ok "
))
if
(
!
(
ptr
=
strchr
(
line
,
'\n'
)))
{
goto
out_err
;
giterr_set
(
GITERR_NET
,
"invalid packet line"
)
;
line
+=
3
;
git__free
(
pkt
)
;
len
-=
3
;
return
-
1
;
}
if
(
line
[
len
-
1
]
==
'\n'
)
len
=
ptr
-
line
;
--
len
;
GITERR_CHECK_ALLOC_ADD
(
&
alloc_len
,
len
,
1
);
GITERR_CHECK_ALLOC_ADD
(
&
alloc_len
,
len
,
1
);
pkt
->
ref
=
git__malloc
(
alloc_len
);
pkt
->
ref
=
git__malloc
(
alloc_len
);
...
@@ -277,6 +285,11 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -277,6 +285,11 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
*
out
=
(
git_pkt
*
)
pkt
;
*
out
=
(
git_pkt
*
)
pkt
;
return
0
;
return
0
;
out_err:
giterr_set
(
GITERR_NET
,
"error parsing OK pkt-line"
);
git__free
(
pkt
);
return
-
1
;
}
}
static
int
ng_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
static
int
ng_pkt
(
git_pkt
**
out
,
const
char
*
line
,
size_t
len
)
...
@@ -293,9 +306,9 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -293,9 +306,9 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
eol
=
line
+
len
;
eol
=
line
+
len
;
if
(
len
<
3
)
if
(
git__prefixncmp
(
line
,
len
,
"ng "
)
)
goto
out_err
;
goto
out_err
;
line
+=
3
;
/* skip "ng " */
line
+=
3
;
if
(
!
(
ptr
=
memchr
(
line
,
' '
,
eol
-
line
)))
if
(
!
(
ptr
=
memchr
(
line
,
' '
,
eol
-
line
)))
goto
out_err
;
goto
out_err
;
...
@@ -337,13 +350,11 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -337,13 +350,11 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
{
{
git_pkt_unpack
*
pkt
;
git_pkt_unpack
*
pkt
;
GIT_UNUSED
(
len
);
pkt
=
git__malloc
(
sizeof
(
*
pkt
));
pkt
=
git__malloc
(
sizeof
(
*
pkt
));
GITERR_CHECK_ALLOC
(
pkt
);
GITERR_CHECK_ALLOC
(
pkt
);
pkt
->
type
=
GIT_PKT_UNPACK
;
pkt
->
type
=
GIT_PKT_UNPACK
;
if
(
!
git__prefixcmp
(
line
,
"unpack ok"
))
if
(
!
git__prefixncmp
(
line
,
len
,
"unpack ok"
))
pkt
->
unpack_ok
=
1
;
pkt
->
unpack_ok
=
1
;
else
else
pkt
->
unpack_ok
=
0
;
pkt
->
unpack_ok
=
0
;
...
@@ -352,13 +363,17 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
...
@@ -352,13 +363,17 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
return
0
;
return
0
;
}
}
static
int
32_t
parse_len
(
const
char
*
line
)
static
int
parse_len
(
size_t
*
out
,
const
char
*
line
,
size_t
linelen
)
{
{
char
num
[
PKT_LEN_SIZE
+
1
];
char
num
[
PKT_LEN_SIZE
+
1
];
int
i
,
k
,
error
;
int
i
,
k
,
error
;
int32_t
len
;
int32_t
len
;
const
char
*
num_end
;
const
char
*
num_end
;
/* Not even enough for the length */
if
(
linelen
<
PKT_LEN_SIZE
)
return
GIT_EBUFS
;
memcpy
(
num
,
line
,
PKT_LEN_SIZE
);
memcpy
(
num
,
line
,
PKT_LEN_SIZE
);
num
[
PKT_LEN_SIZE
]
=
'\0'
;
num
[
PKT_LEN_SIZE
]
=
'\0'
;
...
@@ -379,7 +394,11 @@ static int32_t parse_len(const char *line)
...
@@ -379,7 +394,11 @@ static int32_t parse_len(const char *line)
if
((
error
=
git__strtol32
(
&
len
,
num
,
&
num_end
,
16
))
<
0
)
if
((
error
=
git__strtol32
(
&
len
,
num
,
&
num_end
,
16
))
<
0
)
return
error
;
return
error
;
return
len
;
if
(
len
<
0
)
return
-
1
;
*
out
=
(
size_t
)
len
;
return
0
;
}
}
/*
/*
...
@@ -396,35 +415,32 @@ static int32_t parse_len(const char *line)
...
@@ -396,35 +415,32 @@ static int32_t parse_len(const char *line)
*/
*/
int
git_pkt_parse_line
(
int
git_pkt_parse_line
(
git_pkt
**
head
,
const
char
*
line
,
const
char
**
out
,
size_t
buff
len
)
git_pkt
**
pkt
,
const
char
**
endptr
,
const
char
*
line
,
size_t
line
len
)
{
{
int
ret
;
int
error
;
int32_t
len
;
size_t
len
;
/* Not even enough for the length */
if
(
bufflen
>
0
&&
bufflen
<
PKT_LEN_SIZE
)
return
GIT_EBUFS
;
len
=
parse_len
(
line
);
if
((
error
=
parse_len
(
&
len
,
line
,
linelen
))
<
0
)
{
if
(
len
<
0
)
{
/*
/*
* If we fail to parse the length, it might be because the
* If we fail to parse the length, it might be
* server is trying to send us the packfile already.
* because the server is trying to send us the
* packfile already or because we do not yet have
* enough data.
*/
*/
if
(
bufflen
>=
4
&&
!
git__prefixcmp
(
line
,
"PACK"
))
{
if
(
error
==
GIT_EBUFS
)
;
else
if
(
!
git__prefixncmp
(
line
,
linelen
,
"PACK"
))
giterr_set
(
GITERR_NET
,
"unexpected pack file"
);
giterr_set
(
GITERR_NET
,
"unexpected pack file"
);
}
else
{
else
giterr_set
(
GITERR_NET
,
"bad packet length"
);
giterr_set
(
GITERR_NET
,
"bad packet length"
);
}
return
error
;
return
-
1
;
}
}
/*
/*
*
If we were given a buffer length, then make sure there is
*
Make sure there is enough in the buffer to satisfy
*
enough in the buffer to satisfy this line
*
this line.
*/
*/
if
(
bufflen
>
0
&&
bufflen
<
(
size_t
)
len
)
if
(
linelen
<
len
)
return
GIT_EBUFS
;
return
GIT_EBUFS
;
/*
/*
...
@@ -447,38 +463,38 @@ int git_pkt_parse_line(
...
@@ -447,38 +463,38 @@ int git_pkt_parse_line(
}
}
if
(
len
==
0
)
{
/* Flush pkt */
if
(
len
==
0
)
{
/* Flush pkt */
*
out
=
line
;
*
endptr
=
line
;
return
flush_pkt
(
head
);
return
flush_pkt
(
pkt
);
}
}
len
-=
PKT_LEN_SIZE
;
/* the encoded length includes its own size */
len
-=
PKT_LEN_SIZE
;
/* the encoded length includes its own size */
if
(
*
line
==
GIT_SIDE_BAND_DATA
)
if
(
*
line
==
GIT_SIDE_BAND_DATA
)
ret
=
data_pkt
(
head
,
line
,
len
);
error
=
data_pkt
(
pkt
,
line
,
len
);
else
if
(
*
line
==
GIT_SIDE_BAND_PROGRESS
)
else
if
(
*
line
==
GIT_SIDE_BAND_PROGRESS
)
ret
=
sideband_progress_pkt
(
head
,
line
,
len
);
error
=
sideband_progress_pkt
(
pkt
,
line
,
len
);
else
if
(
*
line
==
GIT_SIDE_BAND_ERROR
)
else
if
(
*
line
==
GIT_SIDE_BAND_ERROR
)
ret
=
sideband_error_pkt
(
head
,
line
,
len
);
error
=
sideband_error_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefix
cmp
(
line
,
"ACK"
))
else
if
(
!
git__prefix
ncmp
(
line
,
len
,
"ACK"
))
ret
=
ack_pkt
(
head
,
line
,
len
);
error
=
ack_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefix
cmp
(
line
,
"NAK"
))
else
if
(
!
git__prefix
ncmp
(
line
,
len
,
"NAK"
))
ret
=
nak_pkt
(
head
);
error
=
nak_pkt
(
pkt
);
else
if
(
!
git__prefix
cmp
(
line
,
"ERR
"
))
else
if
(
!
git__prefix
ncmp
(
line
,
len
,
"ERR
"
))
ret
=
err_pkt
(
head
,
line
,
len
);
error
=
err_pkt
(
pkt
,
line
,
len
);
else
if
(
*
line
==
'#'
)
else
if
(
*
line
==
'#'
)
ret
=
comment_pkt
(
head
,
line
,
len
);
error
=
comment_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefix
cmp
(
line
,
"ok"
))
else
if
(
!
git__prefix
ncmp
(
line
,
len
,
"ok"
))
ret
=
ok_pkt
(
head
,
line
,
len
);
error
=
ok_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefix
cmp
(
line
,
"ng"
))
else
if
(
!
git__prefix
ncmp
(
line
,
len
,
"ng"
))
ret
=
ng_pkt
(
head
,
line
,
len
);
error
=
ng_pkt
(
pkt
,
line
,
len
);
else
if
(
!
git__prefix
cmp
(
line
,
"unpack"
))
else
if
(
!
git__prefix
ncmp
(
line
,
len
,
"unpack"
))
ret
=
unpack_pkt
(
head
,
line
,
len
);
error
=
unpack_pkt
(
pkt
,
line
,
len
);
else
else
ret
=
ref_pkt
(
head
,
line
,
len
);
error
=
ref_pkt
(
pkt
,
line
,
len
);
*
out
=
line
+
len
;
*
endptr
=
line
+
len
;
return
ret
;
return
error
;
}
}
void
git_pkt_free
(
git_pkt
*
pkt
)
void
git_pkt_free
(
git_pkt
*
pkt
)
...
...
src/transports/smart_protocol.c
View file @
ce8803a2
...
@@ -44,7 +44,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
...
@@ -44,7 +44,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
do
{
do
{
if
(
buf
->
offset
>
0
)
if
(
buf
->
offset
>
0
)
error
=
git_pkt_parse_line
(
&
pkt
,
buf
->
data
,
&
line_end
,
buf
->
offset
);
error
=
git_pkt_parse_line
(
&
pkt
,
&
line_end
,
buf
->
data
,
buf
->
offset
);
else
else
error
=
GIT_EBUFS
;
error
=
GIT_EBUFS
;
...
@@ -217,7 +217,7 @@ static int recv_pkt(git_pkt **out_pkt, git_pkt_type *out_type, gitno_buffer *buf
...
@@ -217,7 +217,7 @@ static int recv_pkt(git_pkt **out_pkt, git_pkt_type *out_type, gitno_buffer *buf
do
{
do
{
if
(
buf
->
offset
>
0
)
if
(
buf
->
offset
>
0
)
error
=
git_pkt_parse_line
(
&
pkt
,
ptr
,
&
line_end
,
buf
->
offset
);
error
=
git_pkt_parse_line
(
&
pkt
,
&
line_end
,
ptr
,
buf
->
offset
);
else
else
error
=
GIT_EBUFS
;
error
=
GIT_EBUFS
;
...
@@ -755,7 +755,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
...
@@ -755,7 +755,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
}
}
while
(
line_len
>
0
)
{
while
(
line_len
>
0
)
{
error
=
git_pkt_parse_line
(
&
pkt
,
line
,
&
line_end
,
line_len
);
error
=
git_pkt_parse_line
(
&
pkt
,
&
line_end
,
line
,
line_len
);
if
(
error
==
GIT_EBUFS
)
{
if
(
error
==
GIT_EBUFS
)
{
/* Buffer the data when the inner packet is split
/* Buffer the data when the inner packet is split
...
@@ -798,8 +798,8 @@ static int parse_report(transport_smart *transport, git_push *push)
...
@@ -798,8 +798,8 @@ static int parse_report(transport_smart *transport, git_push *push)
for
(;;)
{
for
(;;)
{
if
(
buf
->
offset
>
0
)
if
(
buf
->
offset
>
0
)
error
=
git_pkt_parse_line
(
&
pkt
,
buf
->
data
,
error
=
git_pkt_parse_line
(
&
pkt
,
&
line_end
,
&
line_end
,
buf
->
offset
);
buf
->
data
,
buf
->
offset
);
else
else
error
=
GIT_EBUFS
;
error
=
GIT_EBUFS
;
...
...
tests/transports/smart/packet.c
0 → 100644
View file @
ce8803a2
#include "clar_libgit2.h"
#include "transports/smart.h"
enum
expected_status
{
PARSE_SUCCESS
,
PARSE_FAILURE
};
static
void
assert_flush_parses
(
const
char
*
line
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_FLUSH
);
cl_assert_equal_strn
(
endptr
,
line
+
4
,
linelen
-
4
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_data_pkt_parses
(
const
char
*
line
,
const
char
*
expected_data
,
size_t
expected_len
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_data
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_DATA
);
cl_assert_equal_i
(
pkt
->
len
,
expected_len
);
cl_assert_equal_strn
(
pkt
->
data
,
expected_data
,
expected_len
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_sideband_progress_parses
(
const
char
*
line
,
const
char
*
expected_data
,
size_t
expected_len
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_progress
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_PROGRESS
);
cl_assert_equal_i
(
pkt
->
len
,
expected_len
);
cl_assert_equal_strn
(
pkt
->
data
,
expected_data
,
expected_len
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_error_parses
(
const
char
*
line
,
const
char
*
expected_error
,
size_t
expected_len
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_err
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_ERR
);
cl_assert_equal_i
(
pkt
->
len
,
expected_len
);
cl_assert_equal_strn
(
pkt
->
error
,
expected_error
,
expected_len
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_ack_parses
(
const
char
*
line
,
const
char
*
expected_oid
,
enum
git_ack_status
expected_status
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_ack
*
pkt
;
git_oid
oid
;
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
expected_oid
));
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_ACK
);
cl_assert_equal_oid
(
&
pkt
->
oid
,
&
oid
);
cl_assert_equal_i
(
pkt
->
status
,
expected_status
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_nak_parses
(
const
char
*
line
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_NAK
);
cl_assert_equal_strn
(
endptr
,
line
+
7
,
linelen
-
7
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_comment_parses
(
const
char
*
line
,
const
char
*
expected_comment
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_comment
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_COMMENT
);
cl_assert_equal_strn
(
pkt
->
comment
,
expected_comment
,
strlen
(
expected_comment
));
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_ok_parses
(
const
char
*
line
,
const
char
*
expected_ref
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_ok
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_OK
);
cl_assert_equal_strn
(
pkt
->
ref
,
expected_ref
,
strlen
(
expected_ref
));
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_unpack_parses
(
const
char
*
line
,
bool
ok
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_unpack
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_UNPACK
);
cl_assert_equal_i
(
pkt
->
unpack_ok
,
ok
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_ng_parses
(
const
char
*
line
,
const
char
*
expected_ref
,
const
char
*
expected_msg
)
{
size_t
linelen
=
strlen
(
line
)
+
1
;
const
char
*
endptr
;
git_pkt_ng
*
pkt
;
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_NG
);
cl_assert_equal_strn
(
pkt
->
ref
,
expected_ref
,
strlen
(
expected_ref
));
cl_assert_equal_strn
(
pkt
->
msg
,
expected_msg
,
strlen
(
expected_msg
));
git_pkt_free
((
git_pkt
*
)
pkt
);
}
#define assert_ref_parses(line, expected_oid, expected_ref, expected_capabilities) \
assert_ref_parses_(line, sizeof(line), expected_oid, expected_ref, expected_capabilities)
static
void
assert_ref_parses_
(
const
char
*
line
,
size_t
linelen
,
const
char
*
expected_oid
,
const
char
*
expected_ref
,
const
char
*
expected_capabilities
)
{
const
char
*
endptr
;
git_pkt_ref
*
pkt
;
git_oid
oid
;
cl_git_pass
(
git_oid_fromstr
(
&
oid
,
expected_oid
));
cl_git_pass
(
git_pkt_parse_line
((
git_pkt
**
)
&
pkt
,
&
endptr
,
line
,
linelen
));
cl_assert_equal_i
(
pkt
->
type
,
GIT_PKT_REF
);
cl_assert_equal_oid
(
&
pkt
->
head
.
oid
,
&
oid
);
cl_assert_equal_strn
(
pkt
->
head
.
name
,
expected_ref
,
strlen
(
expected_ref
));
if
(
expected_capabilities
)
cl_assert_equal_strn
(
pkt
->
capabilities
,
expected_capabilities
,
strlen
(
expected_capabilities
));
else
cl_assert_equal_p
(
NULL
,
pkt
->
capabilities
);
git_pkt_free
((
git_pkt
*
)
pkt
);
}
static
void
assert_pkt_fails
(
const
char
*
line
)
{
const
char
*
endptr
;
git_pkt
*
pkt
;
cl_git_fail
(
git_pkt_parse_line
(
&
pkt
,
&
endptr
,
line
,
strlen
(
line
)
+
1
));
}
void
test_transports_smart_packet__parsing_garbage_fails
(
void
)
{
assert_pkt_fails
(
"0foobar"
);
assert_pkt_fails
(
"00foobar"
);
assert_pkt_fails
(
"000foobar"
);
assert_pkt_fails
(
"0001"
);
assert_pkt_fails
(
""
);
assert_pkt_fails
(
"0"
);
assert_pkt_fails
(
"0i00"
);
assert_pkt_fails
(
"f"
);
}
void
test_transports_smart_packet__flush_parses
(
void
)
{
assert_flush_parses
(
"0000"
);
assert_flush_parses
(
"0000foobar"
);
}
void
test_transports_smart_packet__data_pkt
(
void
)
{
assert_pkt_fails
(
"000foobar"
);
assert_pkt_fails
(
"0001o"
);
assert_pkt_fails
(
"0001
\1
"
);
assert_data_pkt_parses
(
"0005
\1
"
,
""
,
0
);
assert_pkt_fails
(
"0009
\1
o"
);
assert_data_pkt_parses
(
"0009
\1
data"
,
"data"
,
4
);
assert_data_pkt_parses
(
"000a
\1
data"
,
"data"
,
5
);
}
void
test_transports_smart_packet__sideband_progress_pkt
(
void
)
{
assert_pkt_fails
(
"0001
\2
"
);
assert_sideband_progress_parses
(
"0005
\2
"
,
""
,
0
);
assert_pkt_fails
(
"0009
\2
o"
);
assert_sideband_progress_parses
(
"0009
\2
data"
,
"data"
,
4
);
assert_sideband_progress_parses
(
"000a
\2
data"
,
"data"
,
5
);
}
void
test_transports_smart_packet__sideband_err_pkt
(
void
)
{
assert_pkt_fails
(
"0001
\3
"
);
assert_error_parses
(
"0005
\3
"
,
""
,
0
);
assert_pkt_fails
(
"0009
\3
o"
);
assert_error_parses
(
"0009
\3
data"
,
"data"
,
4
);
assert_error_parses
(
"000a
\3
data"
,
"data"
,
5
);
}
void
test_transports_smart_packet__ack_pkt
(
void
)
{
assert_ack_parses
(
"0030ACK 0000000000000000000000000000000000000000"
,
"0000000000000000000000000000000000000000"
,
0
);
assert_ack_parses
(
"0039ACK 0000000000000000000000000000000000000000 continue"
,
"0000000000000000000000000000000000000000"
,
GIT_ACK_CONTINUE
);
assert_ack_parses
(
"0037ACK 0000000000000000000000000000000000000000 common"
,
"0000000000000000000000000000000000000000"
,
GIT_ACK_COMMON
);
assert_ack_parses
(
"0037ACK 0000000000000000000000000000000000000000 ready"
,
"0000000000000000000000000000000000000000"
,
GIT_ACK_READY
);
/* these should fail as they don't have OIDs */
assert_pkt_fails
(
"0007ACK"
);
assert_pkt_fails
(
"0008ACK "
);
/* this one is missing a space and should thus fail */
assert_pkt_fails
(
"0036ACK00000000000000000x0000000000000000000000 ready"
);
/* the following ones have invalid OIDs and should thus fail */
assert_pkt_fails
(
"0037ACK 00000000000000000x0000000000000000000000 ready"
);
assert_pkt_fails
(
"0036ACK 000000000000000000000000000000000000000 ready"
);
assert_pkt_fails
(
"0036ACK 00000000000000000x0000000000000000000000ready"
);
/* this one has an invalid status and should thus fail */
assert_pkt_fails
(
"0036ACK 0000000000000000000000000000000000000000 read"
);
}
void
test_transports_smart_packet__nak_pkt
(
void
)
{
assert_nak_parses
(
"0007NAK"
);
assert_pkt_fails
(
"0007NaK"
);
assert_pkt_fails
(
"0007nak"
);
assert_nak_parses
(
"0007NAKfoobar"
);
assert_pkt_fails
(
"0007nakfoobar"
);
assert_pkt_fails
(
"0007 NAK"
);
}
void
test_transports_smart_packet__error_pkt
(
void
)
{
assert_pkt_fails
(
"0007ERR"
);
assert_pkt_fails
(
"0008ERRx"
);
assert_error_parses
(
"0008ERR "
,
""
,
0
);
assert_error_parses
(
"000EERR ERRMSG"
,
"ERRMSG"
,
6
);
}
void
test_transports_smart_packet__comment_pkt
(
void
)
{
assert_comment_parses
(
"0005#"
,
""
);
assert_comment_parses
(
"000B#foobar"
,
"#fooba"
);
assert_comment_parses
(
"000C#foobar"
,
"#foobar"
);
assert_comment_parses
(
"001A#this is a comment
\n
foo"
,
"#this is a comment
\n
foo"
);
}
void
test_transports_smart_packet__ok_pkt
(
void
)
{
assert_pkt_fails
(
"0007ok
\n
"
);
assert_ok_parses
(
"0007ok "
,
""
);
assert_ok_parses
(
"0008ok
\n
"
,
""
);
assert_ok_parses
(
"0008ok x"
,
"x"
);
assert_ok_parses
(
"0009ok x
\n
"
,
"x"
);
assert_pkt_fails
(
"001OK ref/foo/bar"
);
assert_ok_parses
(
"0012ok ref/foo/bar"
,
"ref/foo/bar"
);
assert_pkt_fails
(
"0013OK ref/foo/bar
\n
"
);
assert_ok_parses
(
"0013ok ref/foo/bar
\n
"
,
"ref/foo/bar"
);
}
void
test_transports_smart_packet__ng_pkt
(
void
)
{
/* TODO: same as for ok pkt */
assert_pkt_fails
(
"0007ng
\n
"
);
assert_pkt_fails
(
"0008ng
\n
"
);
assert_pkt_fails
(
"000Bng ref
\n
"
);
assert_pkt_fails
(
"000Bng ref
\n
"
);
/* TODO: is this a valid packet line? Probably not. */
assert_ng_parses
(
"000Ang x
\n
"
,
""
,
"x"
);
assert_ng_parses
(
"000Fng ref msg
\n
"
,
"ref"
,
"msg"
);
assert_ng_parses
(
"000Fng ref msg
\n
"
,
"ref"
,
"msg"
);
}
void
test_transports_smart_packet__unpack_pkt
(
void
)
{
assert_unpack_parses
(
"000Dunpack ok"
,
1
);
assert_unpack_parses
(
"000Dunpack ng error-msg"
,
0
);
/* TODO: the following tests should fail */
assert_unpack_parses
(
"000Aunpack"
,
0
);
assert_unpack_parses
(
"0011unpack foobar"
,
0
);
assert_unpack_parses
(
"0010unpack ng ok"
,
0
);
assert_unpack_parses
(
"0010unpack okfoo"
,
1
);
}
void
test_transports_smart_packet__ref_pkt
(
void
)
{
assert_pkt_fails
(
"002C0000000000000000000000000000000000000000"
);
assert_pkt_fails
(
"002D0000000000000000000000000000000000000000
\n
"
);
assert_pkt_fails
(
"00300000000000000000000000000000000000000000HEAD"
);
assert_pkt_fails
(
"004800000000x0000000000000000000000000000000 refs/heads/master
\0
multi_ack"
);
assert_ref_parses
(
"003F0000000000000000000000000000000000000000 refs/heads/master
\0
"
,
"0000000000000000000000000000000000000000"
,
"refs/heads/master"
,
""
);
assert_ref_parses
(
"00480000000000000000000000000000000000000000 refs/heads/master
\0
multi_ack"
,
"0000000000000000000000000000000000000000"
,
"refs/heads/master"
,
"multi_ack"
);
assert_ref_parses
(
"00460000000000000000000000000000000000000000 refs/heads/master
\0
one two"
,
"0000000000000000000000000000000000000000"
,
"refs/heads/master"
,
"one two"
);
assert_ref_parses
(
"00310000000000000000000000000000000000000000 HEAD"
,
"0000000000000000000000000000000000000000"
,
"HEAD"
,
NULL
);
assert_pkt_fails
(
"0031000000000000000000000000000000000000000 HEAD"
);
assert_ref_parses
(
"00360000000000000000000000000000000000000000 HEAD HEAD"
,
"0000000000000000000000000000000000000000"
,
"HEAD HEAD"
,
NULL
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment