Skip to content
This repository was archived by the owner on Oct 29, 2021. It is now read-only.

Commit e3db0e9

Browse files
committed
Merge remote-tracking branch 'upstream/master'
Conflicts: Makefile.am README.markdown src/resolver.h tests/check_parser.c tests/test_resolver.c
2 parents c4580c9 + 9931ad4 commit e3db0e9

7 files changed

Lines changed: 175 additions & 39 deletions

File tree

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
0.9.1
2+
- Fixed bug #95 (DNS lookup failing on Cygwin)
3+
- Removed dependency on the check package
24

35
0.9.0
46
- IPv6 support

Makefile.am

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ TESTS = tests/check_parser tests/test_sha1 tests/test_md5 tests/test_rand \
7575
check_PROGRAMS = $(TESTS)
7676

7777
tests_check_parser_SOURCES = tests/check_parser.c tests/test.h
78-
tests_check_parser_CFLAGS = @check_CFLAGS@ $(PARSER_CFLAGS) $(MESODE_FLAGS) \
78+
tests_check_parser_CFLAGS = $(PARSER_CFLAGS) $(MESODE_FLAGS) \
7979
-I$(top_srcdir)/src
80-
tests_check_parser_LDADD = @check_LIBS@ $(MESODE_LIBS)
80+
tests_check_parser_LDADD = $(MESODE_LIBS)
8181
tests_check_parser_LDFLAGS = -static
8282

8383
tests_test_ctx_SOURCES = tests/test_ctx.c

configure.ac

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ PARSER_LIBS=$expat_LIBS
3535
AC_ARG_ENABLE([tls],
3636
[AS_HELP_STRING([--disable-tls], [disable TLS support])])
3737

38-
PKG_CHECK_MODULES([check], [check >= 0.9.4],
39-
[], [AC_MSG_WARN([libcheck not found; unit tests will not be compilable])])
40-
4138
if test "x$enable_tls" != xno; then
4239
PKG_CHECK_MODULES([openssl], [openssl],
4340
[PC_REQUIRES="openssl ${PC_REQUIRES}"],

src/resolver.c

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "ostypes.h"
2222
#include "snprintf.h"
23+
#include "util.h" /* xmpp_min */
2324
#include "resolver.h"
2425

2526
#define MESSAGE_HEADER_LEN 12
@@ -55,41 +56,90 @@ static uint8_t message_header_rcode(const struct message_header *header)
5556
return header->octet3 & 0x0f;
5657
}
5758

59+
/*
60+
* Append a label or a dot to the target name with buffer overflow checks.
61+
* Returns length of the non-truncated resulting string, may be bigger than
62+
* name_max.
63+
*/
64+
static size_t message_name_append_safe(char *name, size_t name_len,
65+
size_t name_max,
66+
const char *tail, size_t tail_len)
67+
{
68+
size_t copy_len;
69+
70+
copy_len = name_max > name_len ? name_max - name_len : 0;
71+
copy_len = xmpp_min(tail_len, copy_len);
72+
if (copy_len > 0)
73+
strncpy(&name[name_len], tail, copy_len);
74+
75+
return name_len + tail_len;
76+
}
77+
78+
/* Returns length of the compressed name. This is NOT the same as strlen(). */
5879
static unsigned message_name_get(const unsigned char *buf, size_t buf_len,
5980
unsigned buf_offset,
6081
char *name, size_t name_max)
6182
{
6283
size_t name_len = 0;
6384
unsigned i = buf_offset;
6485
unsigned pointer;
86+
unsigned rc;
6587
unsigned char label_len;
6688

67-
while ((label_len = buf[i++]) != 0) {
68-
/* label */
89+
90+
while (1) {
91+
if (i >= buf_len) return 0;
92+
label_len = buf[i++];
93+
if (label_len == 0) break;
94+
95+
/* Label */
6996
if ((label_len & 0xc0) == 0) {
97+
if (i + label_len - 1 >= buf_len) return 0;
7098
if (name != NULL) {
71-
if (name_len != 0)
72-
name[name_len++] = '.';
73-
strncpy(&name[name_len], (char *)&buf[i], label_len);
99+
name_len = message_name_append_safe(name, name_len, name_max,
100+
(char *)&buf[i], label_len);
101+
name_len = message_name_append_safe(name, name_len, name_max,
102+
".", 1);
74103
}
75104
i += label_len;
76-
name_len += label_len;
77105

78-
/* pointer */
106+
/* Pointer */
79107
} else if ((label_len & 0xc0) == 0xc0) {
108+
if (i >= buf_len) return 0;
80109
pointer = (label_len & 0x3f) << 8 | buf[i++];
81-
(void)message_name_get(buf, buf_len, pointer, &name[name_len],
82-
name_max - name_len);
83-
/* pointer is always the last */
110+
if (name != NULL && name_len >= name_max && name_max > 0) {
111+
/* We have filled the name buffer. Don't pass it recursively. */
112+
name[name_max - 1] = '\0';
113+
name = NULL;
114+
name_max = 0;
115+
}
116+
rc = message_name_get(buf, buf_len, pointer,
117+
name != NULL ? &name[name_len] : NULL,
118+
name_max > name_len ? name_max - name_len : 0);
119+
if (rc == 0) return 0;
120+
/* Pointer is always the last. */
84121
break;
85122

86123
/* The 10 and 01 combinations are reserved for future use. */
87124
} else {
88125
return 0;
89126
}
90127
}
91-
if (label_len == 0 && name != NULL)
92-
name[name_len] = '\0';
128+
if (label_len == 0) {
129+
if (name_len == 0) name_len = 1;
130+
/*
131+
* At this point name_len is length of the resulting name,
132+
* including '\0'. This value can be exported to allocate buffer
133+
* of precise size.
134+
*/
135+
if (name != NULL && name_max > 0) {
136+
/*
137+
* Overwrite leading '.' with a '\0'. If the resulting name is
138+
* bigger than name_max it is truncated.
139+
*/
140+
name[xmpp_min(name_len, name_max) - 1] = '\0';
141+
}
142+
}
93143

94144
return i - buf_offset;
95145
}
@@ -157,6 +207,15 @@ static void resolver_srv_list_sort(resolver_srv_rr_t **srv_rr_list)
157207
*srv_rr_list = rr_head;
158208
}
159209

210+
#define BUF_OVERFLOW_CHECK(ptr, len) do { \
211+
if ((ptr) >= (len)) { \
212+
if (*srv_rr_list != NULL) \
213+
resolver_srv_free(ctx, *srv_rr_list); \
214+
*srv_rr_list = NULL; \
215+
return XMPP_DOMAIN_NOT_FOUND; \
216+
} \
217+
} while (0)
218+
160219
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
161220
size_t len, resolver_srv_rr_t **srv_rr_list)
162221
{
@@ -190,17 +249,20 @@ int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
190249

191250
/* skip question section */
192251
for (i = 0; i < header.qdcount; ++i) {
252+
BUF_OVERFLOW_CHECK(j, len);
193253
name_len = message_name_len(buf, len, j);
194-
if (name_len == 0) {
195-
/* error in name format */
196-
return XMPP_DOMAIN_NOT_FOUND;
197-
}
254+
/* error in name format */
255+
if (name_len == 0) return XMPP_DOMAIN_NOT_FOUND;
198256
j += name_len + 4;
199257
}
200258

201259
for (i = 0; i < header.ancount; ++i) {
260+
BUF_OVERFLOW_CHECK(j, len);
202261
name_len = message_name_len(buf, len, j);
262+
/* error in name format */
263+
if (name_len == 0) return XMPP_DOMAIN_NOT_FOUND;
203264
j += name_len;
265+
BUF_OVERFLOW_CHECK(j + 16, len);
204266
type = xmpp_ntohs_ptr(&buf[j]);
205267
class = xmpp_ntohs_ptr(&buf[j + 2]);
206268
rdlength = xmpp_ntohs_ptr(&buf[j + 8]);

src/util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
#include "ostypes.h"
2020

21+
/* TODO evaluate x and y only once */
22+
#define xmpp_min(x, y) ((x) < (y) ? (x) : (y))
23+
2124
/* string functions */
2225
char *xmpp_strtok_r(char *s, const char *delim, char **saveptr);
2326

tests/check_parser.c

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,34 @@
1010
*/
1111

1212
#include <stdlib.h>
13+
#include <stdio.h>
1314
#include <string.h>
1415

15-
#include <check.h>
16-
1716
#include <mesode.h>
1817
#include "parser.h"
1918

2019
#include "test.h"
2120

22-
START_TEST(create_destroy)
21+
#define fail_unless(expr) do { \
22+
int result = (expr); \
23+
if (!result) { \
24+
printf("%s:%d: Assertion failed: %s\n", \
25+
__FILE__, __LINE__, #expr); \
26+
exit(1); \
27+
} \
28+
} while (0)
29+
30+
static void create_destroy(void)
2331
{
2432
xmpp_ctx_t *ctx;
2533
parser_t *parser;
2634

2735
ctx = xmpp_ctx_new(NULL, NULL);
2836
parser = parser_new(ctx, NULL, NULL, NULL, NULL);
29-
fail_unless(parser != NULL, "Parser creation failed.");
37+
fail_unless(parser != NULL);
3038
parser_free(parser);
3139
xmpp_ctx_free(ctx);
3240
}
33-
END_TEST
3441

3542
int cbtest_got_start = 0;
3643
void cbtest_handle_start(char *name, char **attrs, void *userdata)
@@ -53,7 +60,7 @@ void cbtest_handle_stanza(xmpp_stanza_t *stanza, void *userdata)
5360
cbtest_got_stanza = 1;
5461
}
5562

56-
START_TEST(callbacks)
63+
static void callbacks(void)
5764
{
5865
xmpp_ctx_t *ctx;
5966
parser_t *parser;
@@ -79,16 +86,18 @@ START_TEST(callbacks)
7986
parser_free(parser);
8087
xmpp_ctx_free(ctx);
8188
}
82-
END_TEST
8389

84-
Suite *parser_suite(void)
90+
int main()
8591
{
86-
Suite *s = suite_create("Parser");
87-
TCase *tc_core = tcase_create("Core");
88-
tcase_add_test(tc_core, create_destroy);
89-
tcase_add_test(tc_core, callbacks);
90-
suite_add_tcase(s, tc_core);
91-
return s;
92-
}
92+
printf("XML parser tests.\n");
9393

94-
TEST_MAIN
94+
printf("create-destroy: ");
95+
create_destroy();
96+
printf("ok\n");
97+
98+
printf("callbacks: ");
99+
callbacks();
100+
printf("ok\n");
101+
102+
return 0;
103+
}

tests/test_resolver.c

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <stdio.h>
1414

1515
#include "mesode.h"
16+
#include "rand.h"
1617
#include "resolver.h"
1718
#include "test.h"
1819

@@ -84,7 +85,6 @@ static const unsigned char data3[] = {
8485
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
8586
0x6d, 0x00,
8687
};
87-
8888
/* res_query("_xmpp-client._tcp.jabber.calyxinstitute.org", C_IN, T_SRV, ...) */
8989
static const unsigned char data4[] = {
9090
0x8d, 0x58, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, // .X........
@@ -103,6 +103,34 @@ static const unsigned char data4[] = {
103103
0x61, 0x6c, 0x79, 0x78, 0x69, 0x6e, 0x73, 0x74, 0x69, 0x74, // alyxinstit
104104
0x75, 0x74, 0x65, 0x03, 0x6f, 0x72, 0x67, 0x00, // ute.org.
105105
};
106+
/* res_query("_xmpp-client._tcp.jabber.org", C_IN, T_SRV, ...) with pointers */
107+
static const unsigned char data5[] = {
108+
0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, // ..........
109+
0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d, 0x70, 0x70, 0x2d, 0x63, // ..._xmpp-c
110+
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, // lient._tcp
111+
0x06, 0x6a, 0x61, 0x62, 0x62, 0x65, 0x72, 0x03, 0x6f, 0x72, // .jabber.or
112+
0x67, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x21, // g..!.....!
113+
0x00, 0x01, 0x00, 0x00, 0x01, 0x9e, 0x00, 0x12, 0x00, 0x1f, // ..........
114+
0x00, 0x1e, 0x14, 0x66, 0x09, 0x68, 0x65, 0x72, 0x6d, 0x65, // ...f.herme
115+
0x73, 0x32, 0x76, 0x36, 0xc0, 0x1e, 0xc0, 0x0c, 0x00, 0x21, // s2v6.....!
116+
0x00, 0x01, 0x00, 0x00, 0x01, 0x9e, 0x00, 0x10, 0x00, 0x1e, // ..........
117+
0x00, 0x1e, 0x14, 0x66, 0x07, 0x68, 0x65, 0x72, 0x6d, 0x65, // ...f.herme
118+
0x73, 0x32, 0xc0, 0x1e, // s2..
119+
};
120+
/* hacked data2 with two empty-string targets. */
121+
static const unsigned char data6[] = {
122+
0xf2, 0x98, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02,
123+
0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
124+
0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
125+
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a,
126+
0x61, 0x62, 0x62, 0x65, 0x72, 0x03, 0x6f, 0x72,
127+
0x67, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c,
128+
0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83,
129+
0x00, 0x07, 0x00, 0x1e, 0x00, 0x1e, 0x14, 0x66,
130+
0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00,
131+
0x00, 0x03, 0x83, 0x00, 0x08, 0x00, 0x1f, 0x00,
132+
0x1e, 0x14, 0x66, 0xc0, 0x40,
133+
};
106134

107135
static const struct {
108136
const unsigned char *data;
@@ -139,22 +167,38 @@ static const struct {
139167
.port = 5222,
140168
.target_nr = 2,
141169
},
170+
{
171+
.data = data5,
172+
.len = sizeof(data5),
173+
.target = "hermes2.jabber.org",
174+
.port = 5222,
175+
.target_nr = 2,
176+
},
177+
{
178+
.data = data6,
179+
.len = sizeof(data6),
180+
.target = "",
181+
.port = 5222,
182+
.target_nr = 2,
183+
},
142184
};
143185

144186
static int srv_rr_list_len(resolver_srv_rr_t *list)
145187
{
146188
int nr;
147189

148-
for(nr = 0; list != NULL; ++nr, list = list->next);
190+
for (nr = 0; list != NULL; ++nr, list = list->next);
149191

150192
return nr;
151193
}
152194

153195
int main(int argc, char **argv)
154196
{
155197
xmpp_ctx_t *ctx;
198+
xmpp_rand_t *rand;
156199
resolver_srv_rr_t *srv_rr_list;
157200
char *domain;
201+
unsigned char *buf;
158202
unsigned short port;
159203
size_t i;
160204
int ret;
@@ -187,6 +231,25 @@ int main(int argc, char **argv)
187231
resolver_srv_free(ctx, srv_rr_list);
188232
}
189233

234+
/*
235+
* The next test case must not crash and is supposed to be checked
236+
* under valgrind.
237+
*/
238+
printf("Test of a broken message: ");
239+
rand = xmpp_rand_new(ctx);
240+
assert(rand != NULL);
241+
assert(sizeof(data2) > 64);
242+
buf = xmpp_alloc(ctx, sizeof(data2));
243+
assert(buf != NULL);
244+
memcpy(buf, data2, 64);
245+
xmpp_rand_bytes(rand, &buf[64], sizeof(data2) - 64);
246+
ret = resolver_srv_lookup_buf(ctx, buf, sizeof(data2), &srv_rr_list);
247+
if (ret == XMPP_DOMAIN_FOUND && srv_rr_list != NULL)
248+
resolver_srv_free(ctx, srv_rr_list);
249+
xmpp_free(ctx, buf);
250+
xmpp_rand_free(ctx, rand);
251+
printf("ok\n");
252+
190253
xmpp_ctx_free(ctx);
191254

192255
return 0;

0 commit comments

Comments
 (0)