/src/FreeRDP/channels/rail/client/test/TestFuzzChannelRail.c
Line | Count | Source |
1 | | /** |
2 | | * FreeRDP: A Remote Desktop Protocol Implementation |
3 | | * libFuzzer harness for rail (Remote Applications Integrated Locally) PDU parsing |
4 | | */ |
5 | | |
6 | | #include <stddef.h> |
7 | | #include <stdint.h> |
8 | | |
9 | | #include <winpr/crt.h> |
10 | | #include <winpr/stream.h> |
11 | | #include <winpr/wlog.h> |
12 | | |
13 | | #include <freerdp/client/rail.h> |
14 | | #include <freerdp/freerdp.h> |
15 | | |
16 | | #include "../rail_main.h" |
17 | | #include "../rail_orders.h" |
18 | | |
19 | | static void dealloc(railPlugin* plugin) |
20 | 0 | { |
21 | 0 | if (!plugin) |
22 | 0 | return; |
23 | 0 | if (plugin->rdpcontext) |
24 | 0 | freerdp_settings_free(plugin->rdpcontext->settings); |
25 | 0 | free(plugin->rdpcontext); |
26 | 0 | free(plugin); |
27 | 0 | } |
28 | | |
29 | | WINPR_ATTR_MALLOC(dealloc, 1) |
30 | | static railPlugin* alloc(void) |
31 | 0 | { |
32 | 0 | railPlugin* rail = (railPlugin*)calloc(1, sizeof(railPlugin)); |
33 | 0 | if (!rail) |
34 | 0 | return nullptr; |
35 | 0 | rail->rdpcontext = calloc(1, sizeof(rdpContext)); |
36 | 0 | if (!rail->rdpcontext) |
37 | 0 | goto fail; |
38 | | |
39 | 0 | rail->rdpcontext->settings = freerdp_settings_new(0); |
40 | 0 | if (!rail->rdpcontext->settings) |
41 | 0 | goto fail; |
42 | 0 | return rail; |
43 | 0 | fail: |
44 | 0 | dealloc(rail); |
45 | 0 | return nullptr; |
46 | 0 | } |
47 | | |
48 | | int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
49 | | { |
50 | | if (size < 2) |
51 | | return 0; |
52 | | if (size > (1u << 20)) |
53 | | return 0; |
54 | | |
55 | | int rc = -1; |
56 | | |
57 | | wLog* root = WLog_GetRoot(); |
58 | | (void)WLog_SetLogLevel(root, WLOG_TRACE); |
59 | | (void)WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK); |
60 | | |
61 | | railPlugin* g_rail = alloc(); |
62 | | RailClientContext* context = (RailClientContext*)calloc(1, sizeof(RailClientContext)); |
63 | | wStream* s = Stream_New(nullptr, size); |
64 | | if (!g_rail || !context || !s) |
65 | | goto fail; |
66 | | |
67 | | g_rail->log = WLog_Get("fuzz.rail"); |
68 | | |
69 | | /* A context is required (handlers bail on nullptr); nullptr callbacks skip dispatch. */ |
70 | | |
71 | | g_rail->context = context; |
72 | | g_rail->channelEntryPoints.pInterface = context; |
73 | | |
74 | | /* rail_order_recv owns and frees the stream (Stream_Free(s, TRUE)); give it an owned copy. */ |
75 | | |
76 | | Stream_Write(s, data, size); |
77 | | Stream_SealLength(s); |
78 | | if (!Stream_SetPosition(s, 0)) |
79 | | goto fail; |
80 | | |
81 | | (void)rail_order_recv(g_rail, s); |
82 | | s = nullptr; // Freed up by rail_order_recv |
83 | | |
84 | | rc = 0; |
85 | | |
86 | | fail: |
87 | | Stream_Free(s, TRUE); |
88 | | free(context); |
89 | | dealloc(g_rail); |
90 | | return rc; |
91 | | } |