55450055d8
This commit is a mix of several commits, squashed into one because the commits before 'Move regex to own Library and fix all the broken stuff' were not fixable in any elegant way. The commits are listed below for "historical" purposes: - AK: Add options/flags and Errors for regular expressions Flags can be provided for any possible flavour by adding a new scoped enum. Handling of flags is done by templated Options class and the overloaded '|' and '&' operators. - AK: Add Lexer for regular expressions The lexer parses the input and extracts tokens needed to parse a regular expression. - AK: Add regex Parser and PosixExtendedParser This patchset adds a abstract parser class that can be derived to implement different parsers. A parser produces bytecode to be executed within the regex matcher. - AK: Add regex matcher This patchset adds an regex matcher based on the principles of the T-REX VM. The bytecode pruduced by the respective Parser is put into the matcher and the VM will recursively execute the bytecode according to the available OpCodes. Possible improvement: the recursion could be replaced by multi threading capabilities. To match a Regular expression, e.g. for the Posix standard regular expression matcher use the following API: ``` Pattern<PosixExtendedParser> pattern("^.*$"); auto result = pattern.match("Well, hello friends!\nHello World!"); // Match whole needle EXPECT(result.count == 1); EXPECT(result.matches.at(0).view.starts_with("Well")); EXPECT(result.matches.at(0).view.end() == "!"); result = pattern.match("Well, hello friends!\nHello World!", PosixFlags::Multiline); // Match line by line EXPECT(result.count == 2); EXPECT(result.matches.at(0).view == "Well, hello friends!"); EXPECT(result.matches.at(1).view == "Hello World!"); EXPECT(pattern.has_match("Well,....")); // Just check if match without a result, which saves some resources. ``` - AK: Rework regex to work with opcodes objects This patchsets reworks the matcher to work on a more structured base. For that an abstract OpCode class and derived classes for the specific OpCodes have been added. The respective opcode logic is contained in each respective execute() method. - AK: Add benchmark for regex - AK: Some optimization in regex for runtime and memory - LibRegex: Move regex to own Library and fix all the broken stuff Now regex works again and grep utility is also in place for testing. This commit also fixes the use of regex.h in C by making `regex_t` an opaque (-ish) type, which makes its behaviour consistent between C and C++ compilers. Previously, <regex.h> would've blown C compilers up, and even if it didn't, would've caused a leak in C code, and not in C++ code (due to the existence of `OwnPtr` inside the struct). To make this whole ordeal easier to deal with (for now), this pulls the definitions of `reg*()` into LibRegex. pros: - The circular dependency between LibC and LibRegex is broken - Eaiser to test (without accidentally pulling in the host's libc!) cons: - Using any of the regex.h functions will require the user to link -lregex - The symbols will be missing from libc, which will be a big surprise down the line (especially with shared libs). Co-Authored-By: Ali Mohammad Pur <ali.mpfard@gmail.com> |
||
---|---|---|
.. | ||
Fuzzers | ||
.gitignore | ||
CMakeLists.txt | ||
ReadMe.md | ||
TestApp.cpp | ||
TestJson.cpp |
Lagom
The Serenity C++ library, for other Operating Systems.
About
If you want to bring the comfortable Serenity classes with you to another system, look no further. This is basically a "port" of the AK
and LibCore
libraries to generic *nix systems.
Lagom is a Swedish word that means "just the right amount." (Wikipedia)
Fuzzing
Lagom can be used to fuzz parts of SerenityOS's code base. This requires buildling with clang
, so it's convenient to use a different build directory for that. Fuzzers work best with Address Sanitizer enabled. Run CMake like this:
# From the root of the SerenityOS checkout:
mkdir BuildLagom && cd BuildLagom
cmake -GNinja -DBUILD_LAGOM=ON -DENABLE_FUZZER_SANITIZER=ON -DENABLE_ADDRESS_SANITIZER=ON -DCMAKE_CXX_COMPILER=clang++ ..
ninja Meta/Lagom/all
# Or as a handy rebuild-rerun line:
ninja FuzzJs && Meta/Lagom/Fuzzers/FuzzJs
Any fuzzing results (particularly slow inputs, crashes, etc.) will be dropped in the current directory.
clang emits different warnings than gcc, so you may have to remove -Werror
in CMakeLists.txt and Meta/Lagom/CMakeLists.txt.
Fuzzers work better if you give them a fuzz corpus, e.g. Meta/Lagom/Fuzzers/FuzzBMP ../Base/res/html/misc/bmpsuite_files/rgba32-61754.bmp
Pay attention that LLVM also likes creating new files, don't blindly commit them (yet)!
To run several fuzz jobs in parallel, pass -jobs=24 -workers=24
.
To get less log output, pass -close_fd_mask=3
-- but that but hides assertion messages. Just 1
only closes stdout.
It's good to move overzealous log output behind FOO_DEBUG
macros.
Analyzing a crash
LLVM fuzzers have a weird interface. In particular, to see the help, you need to call it with -help=1
, and it will ignore --help
and -help
.
To reproduce a crash, run it like this: MyFuzzer crash-27480a219572aa5a11b285968a3632a4cf25388e
To reproduce a crash in gdb, you want to disable various signal handlers, so that gdb sees the actual location of the crash:
$ gdb ./Meta/Lagom/Fuzzers/FuzzBMP
<... SNIP some output ...>
(gdb) run -handle_abrt=0 -handle_segv=0 crash-27480a219572aa5a11b285968a3632a4cf25388e
<... SNIP some output ...>
FuzzBMP: ../../Libraries/LibGfx/Bitmap.cpp:84: Gfx::Bitmap::Bitmap(Gfx::BitmapFormat, const Gfx::IntSize &, Gfx::Bitmap::Purgeable): Assertion `m_data && m_data != (void*)-1' failed.
Thread 1 "FuzzBMP" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: File or directory not found.
(gdb)