Coverage Report

Created: 2026-10-15 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
1.20k
{
21
1.20k
  if (!plugin)
22
0
    return;
23
1.20k
  if (plugin->rdpcontext)
24
1.20k
    freerdp_settings_free(plugin->rdpcontext->settings);
25
1.20k
  free(plugin->rdpcontext);
26
1.20k
  free(plugin);
27
1.20k
}
28
29
WINPR_ATTR_MALLOC(dealloc, 1)
30
static railPlugin* alloc(void)
31
1.20k
{
32
1.20k
  railPlugin* rail = (railPlugin*)calloc(1, sizeof(railPlugin));
33
1.20k
  if (!rail)
34
0
    return nullptr;
35
1.20k
  rail->rdpcontext = calloc(1, sizeof(rdpContext));
36
1.20k
  if (!rail->rdpcontext)
37
0
    goto fail;
38
39
1.20k
  rail->rdpcontext->settings = freerdp_settings_new(0);
40
1.20k
  if (!rail->rdpcontext->settings)
41
0
    goto fail;
42
1.20k
  return rail;
43
0
fail:
44
0
  dealloc(rail);
45
0
  return nullptr;
46
1.20k
}
47
48
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
49
1.20k
{
50
1.20k
  if (size < 2)
51
1
    return 0;
52
1.20k
  if (size > (1u << 20))
53
0
    return 0;
54
55
1.20k
  int rc = -1;
56
57
1.20k
  wLog* root = WLog_GetRoot();
58
1.20k
  (void)WLog_SetLogLevel(root, WLOG_TRACE);
59
1.20k
  (void)WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK);
60
61
1.20k
  railPlugin* g_rail = alloc();
62
1.20k
  RailClientContext* context = (RailClientContext*)calloc(1, sizeof(RailClientContext));
63
1.20k
  wStream* s = Stream_New(nullptr, size);
64
1.20k
  if (!g_rail || !context || !s)
65
0
    goto fail;
66
67
1.20k
  g_rail->log = WLog_Get("fuzz.rail");
68
69
  /* A context is required (handlers bail on nullptr); nullptr callbacks skip dispatch. */
70
71
1.20k
  g_rail->context = context;
72
1.20k
  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
1.20k
  Stream_Write(s, data, size);
77
1.20k
  Stream_SealLength(s);
78
1.20k
  if (!Stream_SetPosition(s, 0))
79
0
    goto fail;
80
81
1.20k
  (void)rail_order_recv(g_rail, s);
82
1.20k
  s = nullptr; // Freed up by rail_order_recv
83
84
1.20k
  rc = 0;
85
86
1.20k
fail:
87
1.20k
  Stream_Free(s, TRUE);
88
1.20k
  free(context);
89
1.20k
  dealloc(g_rail);
90
1.20k
  return rc;
91
1.20k
}