NeoMutt  2025-12-11-800-ga0ee0f
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
cli.c
Go to the documentation of this file.
1
22
23#include "config.h"
24#include <ctype.h>
25#include <stdbool.h>
26#include <stdint.h>
27#include <string.h>
28#include <unistd.h>
29#include "mutt/lib.h"
30#include "cli/lib.h"
31
32bool StartupComplete = true;
33
46static bool parse_args(const uint8_t *data, size_t size, int *argc, char ***argv)
47{
48 // Limit input size to prevent excessive memory usage
49 if (size > 4096)
50 return false;
51
52 // Create a null-terminated copy of the input
53 char *input = MUTT_MEM_MALLOC(size + 1, char);
54 memcpy(input, data, size);
55 input[size] = '\0';
56
57 // Count arguments (words separated by spaces/control chars)
58 int count = 1; // Start with 1 for argv[0] = "neomutt"
59 bool in_word = false;
60
61 for (size_t i = 0; i < size; i++)
62 {
63 unsigned char c = (unsigned char) input[i];
64 // Treat control characters and space as separators
65 if (iscntrl(c) || (c == ' '))
66 {
67 input[i] = '\0';
68 in_word = false;
69 }
70 else if (!in_word)
71 {
72 count++;
73 in_word = true;
74 }
75 }
76
77 // Allocate argv array
78 char **args = MUTT_MEM_MALLOC(count + 1, char *);
79 args[0] = mutt_str_dup("neomutt");
80
81 // Fill in arguments
82 int idx = 1;
83 in_word = false;
84 char *word_start = NULL;
85
86 for (size_t i = 0; i < size; i++)
87 {
88 if (input[i] == '\0')
89 {
90 if (in_word && word_start)
91 {
92 args[idx++] = mutt_str_dup(word_start);
93 word_start = NULL;
94 }
95 in_word = false;
96 }
97 else if (!in_word)
98 {
99 word_start = &input[i];
100 in_word = true;
101 }
102 }
103
104 // Handle last word if input doesn't end with separator
105 if (in_word && word_start)
106 {
107 args[idx++] = mutt_str_dup(word_start);
108 }
109
110 args[idx] = NULL;
111 FREE(&input);
112
113 *argc = idx;
114 *argv = args;
115 return true;
116}
117
123static void free_args(int argc, char **argv)
124{
125 for (int i = 0; i < argc; i++)
126 {
127 FREE(&argv[i]);
128 }
129 FREE(&argv);
130}
131
132int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
133{
135
136 int argc = 0;
137 char **argv = NULL;
138
139 if (!parse_args(data, size, &argc, &argv))
140 return -1;
141
142 // Disable getopt error output to stderr
143 opterr = 0;
144
145 struct CommandLine *cli = command_line_new();
146 cli_parse(argc, (char *const *) argv, cli);
147 command_line_free(&cli);
148
149 free_args(argc, argv);
150
151 return 0;
152}
Parse the Command Line.
bool cli_parse(int argc, char *const *argv, struct CommandLine *cli)
Parse the Command Line.
Definition parse.c:148
static void free_args(int argc, char **argv)
Free the allocated argc/argv.
Definition cli.c:123
static bool parse_args(const uint8_t *data, size_t size, int *argc, char ***argv)
Parse fuzz input into argc/argv format.
Definition cli.c:46
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition cli.c:132
bool StartupComplete
When the config has been read.
Definition address.c:11
int log_disp_null(time_t stamp, const char *file, int line, const char *function, enum LogLevel level, const char *format,...)
Discard log lines - Implements log_dispatcher_t -.
Definition logging.c:515
int log_dispatcher_t MuttLogger
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
struct CommandLine * command_line_new(void)
Create a new CommandLine.
Definition objects.c:105
void command_line_free(struct CommandLine **ptr)
Free a CommandLine.
Definition objects.c:114
Command Line options.
Definition objects.h:128