/src/pjsip/tests/fuzz/fuzz-presence.c
Line | Count | Source |
1 | | #include <stdint.h> |
2 | | #include <stdlib.h> |
3 | | #include <string.h> |
4 | | #include <limits.h> |
5 | | #include <pjsip.h> |
6 | | #include <pjlib.h> |
7 | | #include <pjsip-simple/pidf.h> |
8 | | #include <pjsip-simple/xpidf.h> |
9 | | #include <pjsip-simple/rpid.h> |
10 | | #include <pjsip-simple/dialog_info.h> |
11 | | #include <pjsip-simple/iscomposing.h> |
12 | | |
13 | 3.31k | #define kMinInputLength 10 |
14 | 1.65k | #define kMaxInputLength 5120 |
15 | | |
16 | | static pj_caching_pool caching_pool; |
17 | | static pj_pool_t *pool = NULL; |
18 | | |
19 | 1.65k | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { |
20 | 1.65k | char print_buf[2048]; |
21 | 1.65k | pj_status_t status; |
22 | 1.65k | int doc_len; |
23 | | |
24 | 1.65k | if (Size < kMinInputLength || Size > kMaxInputLength) { |
25 | 10 | return 0; |
26 | 10 | } |
27 | | |
28 | 1.64k | status = pj_init(); |
29 | 1.64k | if (status != PJ_SUCCESS) { |
30 | 0 | return 0; |
31 | 0 | } |
32 | | |
33 | 1.64k | pj_log_set_level(0); |
34 | 1.64k | pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, 0); |
35 | | |
36 | 1.64k | pool = pj_pool_create(&caching_pool.factory, "fuzz-presence", 4000, 4000, NULL); |
37 | 1.64k | if (!pool) { |
38 | 0 | pj_caching_pool_destroy(&caching_pool); |
39 | 0 | return 0; |
40 | 0 | } |
41 | | |
42 | | /* Clamp size to INT_MAX to avoid truncation issues */ |
43 | 1.64k | if (Size > INT_MAX) { |
44 | 0 | Size = INT_MAX; |
45 | 0 | } |
46 | 1.64k | doc_len = (int)Size; |
47 | | |
48 | 1.64k | char *doc = pj_pool_alloc(pool, Size + 1); |
49 | 1.64k | if (!doc) { |
50 | 0 | pj_pool_release(pool); |
51 | 0 | pj_caching_pool_destroy(&caching_pool); |
52 | 0 | return 0; |
53 | 0 | } |
54 | 1.64k | memcpy(doc, Data, Size); |
55 | 1.64k | doc[Size] = '\0'; |
56 | | |
57 | | /* Test PIDF parser */ |
58 | 1.64k | pjpidf_pres *pidf_pres = pjpidf_parse(pool, doc, doc_len); |
59 | 1.64k | if (pidf_pres) { |
60 | 751 | pjpidf_print(pidf_pres, print_buf, sizeof(print_buf)); |
61 | | |
62 | 751 | pjpidf_tuple *tuple = pjpidf_pres_get_first_tuple(pidf_pres); |
63 | 751 | if (tuple) { |
64 | | /* Call only safe accessor functions without assertions */ |
65 | 130 | pjpidf_tuple_get_contact(tuple); |
66 | 130 | pjpidf_tuple_get_timestamp(tuple); |
67 | | |
68 | 130 | pjpidf_note *note = pjpidf_tuple_get_first_note(tuple); |
69 | 403 | while (note) { |
70 | 273 | note = pjpidf_tuple_get_next_note(tuple, note); |
71 | 273 | } |
72 | 130 | } |
73 | | |
74 | 751 | pjpidf_pres_get_first_note(pidf_pres); |
75 | | |
76 | | /* Test RPID within PIDF */ |
77 | 751 | pjrpid_element rpid_elem; |
78 | 751 | if (pjrpid_get_element(pidf_pres, pool, &rpid_elem) == PJ_SUCCESS) { |
79 | 287 | (void)rpid_elem.type; |
80 | 287 | (void)rpid_elem.activity; |
81 | 287 | if (rpid_elem.note.slen > 0) { |
82 | 2 | (void)rpid_elem.note.ptr; |
83 | 2 | } |
84 | 287 | } |
85 | 751 | } |
86 | | |
87 | | /* Test XPIDF parser */ |
88 | 1.64k | pjxpidf_pres *xpidf_pres = pjxpidf_parse(pool, doc, (pj_size_t)Size); |
89 | 1.64k | if (xpidf_pres) { |
90 | 35 | pjxpidf_print(xpidf_pres, print_buf, sizeof(print_buf)); |
91 | 35 | pjxpidf_get_uri(xpidf_pres); |
92 | 35 | pjxpidf_get_status(xpidf_pres); |
93 | 35 | } |
94 | | |
95 | | /* Test Dialog-Info parser */ |
96 | 1.64k | pjsip_dlg_info_dialog *dlg_info = pjsip_dlg_info_parse(pool, doc, doc_len); |
97 | 1.64k | if (dlg_info) { |
98 | 1 | pj_xml_attr *attr = dlg_info->attr_head.next; |
99 | 1 | while (attr != &dlg_info->attr_head) { |
100 | 0 | if (attr->name.slen > 0) (void)attr->name.ptr; |
101 | 0 | if (attr->value.slen > 0) (void)attr->value.ptr; |
102 | 0 | attr = attr->next; |
103 | 0 | } |
104 | | |
105 | 1 | pj_xml_node *child = dlg_info->node_head.next; |
106 | 1 | while (child != (pj_xml_node*)&dlg_info->node_head) { |
107 | 0 | if (child->name.slen > 0) (void)child->name.ptr; |
108 | 0 | if (child->content.slen > 0) (void)child->content.ptr; |
109 | 0 | child = child->next; |
110 | 0 | } |
111 | 1 | } |
112 | | |
113 | | /* Test Iscomposing parser */ |
114 | 1.64k | pj_bool_t is_composing = PJ_FALSE; |
115 | 1.64k | pj_str_t *last_active = NULL; |
116 | 1.64k | pj_str_t *content_type = NULL; |
117 | 1.64k | int refresh = 0; |
118 | | |
119 | 1.64k | if (pjsip_iscomposing_parse(pool, doc, (pj_size_t)Size, |
120 | 1.64k | &is_composing, &last_active, |
121 | 1.64k | &content_type, &refresh) == PJ_SUCCESS) { |
122 | 43 | (void)is_composing; |
123 | 43 | (void)refresh; |
124 | 43 | if (last_active && last_active->slen > 0) (void)last_active->ptr; |
125 | 43 | if (content_type && content_type->slen > 0) (void)content_type->ptr; |
126 | 43 | } |
127 | | |
128 | 1.64k | pj_pool_release(pool); |
129 | 1.64k | pj_caching_pool_destroy(&caching_pool); |
130 | 1.64k | return 0; |
131 | 1.64k | } |
132 | | |