/src/FreeRDP/winpr/libwinpr/clipboard/test/TestFuzzWinPRClipboard.c
Line | Count | Source |
1 | | /** |
2 | | * FreeRDP: A Remote Desktop Protocol Implementation |
3 | | * libFuzzer harness for the WinPR clipboard format synthesizers |
4 | | * |
5 | | * The cliprdr channel hands remote (attacker-controlled) clipboard payloads to |
6 | | * WinPR's clipboard subsystem, which converts between formats on demand using |
7 | | * the synthesizers in synthetic.c / synthetic_file.c (CF_DIB <-> bitmap file, |
8 | | * "HTML Format" <-> text/html, FileGroupDescriptorW <-> text/uri-list, ...). |
9 | | * Those parsers consume untrusted bytes but are not otherwise fuzzed. |
10 | | * |
11 | | * This harness registers a source format, stores the fuzz input under it, then |
12 | | * requests every other registered format so each applicable synthesizer parses |
13 | | * the payload. |
14 | | */ |
15 | | |
16 | | #include <stddef.h> |
17 | | #include <stdint.h> |
18 | | |
19 | | #include <winpr/crt.h> |
20 | | #include <winpr/clipboard.h> |
21 | | #include <winpr/wlog.h> |
22 | | |
23 | | static const char* kSourceFormats[] = { "CF_DIB", |
24 | | "CF_DIBV5", |
25 | | "HTML Format", |
26 | | "text/html", |
27 | | "image/bmp", |
28 | | "image/png", |
29 | | "FileGroupDescriptorW", |
30 | | "text/uri-list", |
31 | | "CF_UNICODETEXT", |
32 | | "CF_TEXT", |
33 | | "CF_OEMTEXT" }; |
34 | | |
35 | | int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
36 | 1.69k | { |
37 | 1.69k | static BOOL loggingInitialized = FALSE; |
38 | | |
39 | 1.69k | if (!loggingInitialized) |
40 | 1 | { |
41 | 1 | (void)WLog_SetLogLevel(WLog_GetRoot(), WLOG_OFF); |
42 | 1 | loggingInitialized = TRUE; |
43 | 1 | } |
44 | | |
45 | 1.69k | if (size < 2) |
46 | 2 | return 0; |
47 | 1.69k | if (size > (1u << 20)) |
48 | 0 | return 0; |
49 | | |
50 | 1.69k | wClipboard* clipboard = ClipboardCreate(); |
51 | 1.69k | if (!clipboard) |
52 | 0 | return 0; |
53 | | |
54 | 1.69k | const size_t count = sizeof(kSourceFormats) / sizeof(kSourceFormats[0]); |
55 | 1.69k | const char* srcName = kSourceFormats[data[0] % count]; |
56 | | |
57 | 1.69k | UINT32 srcId = ClipboardRegisterFormat(clipboard, srcName); |
58 | 1.69k | if (srcId != 0) |
59 | 1.69k | { |
60 | | /* Store the remaining bytes as the (attacker) payload for srcName. */ |
61 | 1.69k | (void)ClipboardSetData(clipboard, srcId, data + 1, (UINT32)(size - 1)); |
62 | | |
63 | 1.69k | UINT32* formatIds = nullptr; |
64 | 1.69k | UINT32 numFormats = ClipboardGetFormatIds(clipboard, &formatIds); |
65 | | |
66 | 7.64k | for (UINT32 i = 0; i < numFormats; i++) |
67 | 5.95k | { |
68 | 5.95k | UINT32 outSize = 0; |
69 | 5.95k | void* out = ClipboardGetData(clipboard, formatIds[i], &outSize); |
70 | 5.95k | free(out); |
71 | 5.95k | } |
72 | 1.69k | free(formatIds); |
73 | 1.69k | } |
74 | | |
75 | 1.69k | ClipboardDestroy(clipboard); |
76 | 1.69k | return 0; |
77 | 1.69k | } |