Previously ByteBuffer::grow() behaved like Vector<T>::resize().
However the function name was somewhat ambiguous - and so this patch
updates ByteBuffer to behave more like Vector<T> by replacing grow()
with resize() and adding an ensure_capacity() method.
This also lets the user change the buffer's capacity without affecting
the size which was not previously possible.
Additionally this patch makes the capacity() method public (again).
Previously, we would go crazy and shift things way out of bounds.
Add tests to verify that the decoding algorithm is safe around the
limits of the result type.
printf didn't check whether the additional integer variable belongs to
the field width specifier or to the precision specifier, and always
applied it to the field width instead.
Implement the case distinction that we already use in literal width
and precision specifiers for the variable version as well so that
they are correctly attributed.
These dbgln's caused excessive load in the WebServer process,
accounting for ~67% of the processing time when serving a webpage
with a bunch of resources like serenityos.org/happy/2nd/.
We want to discourage folks from using APIs which lull you into a sense
of false safety in terms of OOM. There are cases where you want to force
allocations to succeed or crash, but those should use a more explicit
API than `AK::adopt_own(.)`.
The ASAN_[UN]POISON_MEMORY_REGION macros can be used to manually notify
the AddressSanitizer runtime about the reachability of instrumented code
accessing a memory region. This is most useful for manually managed
heaps and arenas that do not go directly to malloc or alligned_alloc.
Previously GCC came to the conclusion that we were reading
m_outline_capacity via ByteBuffer(ByteBuffer const&) -> grow()
-> capacity() even though that could never be the case because
m_size is 0 at that point which means we have an inline buffer
and capacity() would return inline_capacity in that case without
reading m_outline_capacity.
This makes GCC inline parts of the grow() function into the
ByteBuffer copy constructor which seems sufficient for GCC to
realize that m_outline_capacity isn't actually being read.
When compiling the Kernel with Og, the compiler complains that
m_outline_capacity might be uninitialized when calling capacity()
Note that this fix is not really what we want. Ideally only outline
buffer and outline capacity would need initialized, not the entire
inline buffer. However, clang considers the class to not be
default-constructible if we make that change, while gcc accepts it.
We had two functions for doing mostly the same thing. Combine both
of them into String::find() and use that everywhere.
Also add some tests to cover basic behavior.
Problem:
- The constructor is defined to be the default constructor.
Solution:
- Let the compiler generate the destructor by setting it to the
default.
We were accidentally calling calculate_base64_decoded_length instead,
which resulted in extra allocations during the StringBuilder::append
calls that can be avoided.
This patch implements a Unicode-safe substring method, which can be used
when offset and length should be specified in actual characters instead
of bytes.
This can be used to mitigate issues where a string is split in the
middle of a UTF-8 multi-byte character, which leads to invalid UTF-8.
Furthermore, it implements to common shorthands for substring methods
which take only an offset and return the substring until the end of the
string.
If a line was larger than 1024 bytes or the file ended without a
newline character, can_read_line would return false.
IODevice::can_read_line() now reads until a newline is found or
EOF is reached.
fixes#5907
This introduces the UnicodeUtils file, which contains helper functions
related to Unicode. This is in contrast to StringUtils, whose functions
are not directly related to Unicode and are, in theory,
encoding-agnostic.
Removing the element from the intrusive linked list might not be safe
if doing so requires a lock. Instead this is something the caller
should have done so let's verify instead that we're not on any lists.
Problem:
- Bitmasks are duplicated.
- Bitmasks are C-style arrays.
Solution:
- Move bitmasks to BitmapView.h.
- Change C-style arrays to be AK::Array for added safety.
Previously <AK/Function.h> also included <AK/OwnPtr.h>. That's about to
change though. This patch fixes a few build problems that will occur
when that change happens.
This changes Variant::visit() to forward the value returned by the
selected visitor invocation. By perfectly forwarding the returned value,
this allows for the visitor to return by value or reference.
Note that all provided visitors must return the same type - the compiler
will otherwise fail with the message: "inconsistent deduction for auto
return type".
Problem:
- Function local `constexpr` variables do not need to be
`static`. This consumes memory which is unnecessary and can prevent
some optimizations.
- C-style arrays are not as safe as AK::Arrays and require the user to
specify the length of the array manually.
Solution:
- Remove `static` keyword.
- Change from C-style array for AK::Array.
In case the write was to stderr/stdout, and it just so happened to fail
because of an issue like "the pty is gone", VERIFY() would end up
calling vout() back to write to stderr, which would then fail forever
until the stack is exhausted.
"Fixes" the issue where the Shell would crash in horrible ways when the
terminal is closed.
Previously StringBuilder would start allocating an external buffer
once the caller has used up more than half of the inline buffer's
capacity. Instead we should prefer to use the inline buffer until
it is full and only then start to allocate an external buffer.
Problem:
- `BitmapView` permits changing the underlying `Bitmap`. This violates
the idea of a "view" since views are simply overlays which can
themselves change but do not change the underlying data.
Solution:
- Migrate all non-`const` member functions to Bitmap.
Problem:
- Static variables take memory and can be subject to less optimization.
- This static variable is only used in 1 place.
Solution:
- Move the variable into the function and make it non-static.
This was removed as part of the ByteBuffer changes but the allocation
optimization is still necessary at least for non-SerenityOS targets
where malloc_good_size() isn't supported or returns a small value and
causes a whole bunch of unnecessary reallocations.
As the parser now flattens out the instructions and inserts synthetic
nesting/structured instructions where needed, we can treat the whole
thing as a simple parsed bytecode stream.
This currently knows how to execute the following instructions:
- unreachable
- nop
- local.get
- local.set
- {i,f}{32,64}.const
- block
- loop
- if/else
- branch / branch_if
- i32_add
- i32_and/or/xor
- i32_ne
This also extends the 'wasm' utility to optionally execute the first
function in the module with optionally user-supplied arguments.
Problem:
- `BitmapView` permits changing the underlying `Bitmap`. This violates
the idea of a "view" since views are simply overlays which can
themselves change but do not change the underlying data.
Solution:
- Migrate all non-`const` member functions to Bitmap.
The current code is factored such that reads to the entirety of the last
byte should be dropped. This was relying on the fact that last would be
one past the end in that case. Instead of actually reading that byte
when it's completely out of bounds of the bitmask, just skip reads that
would be invalid. Add more tests to make sure that the behavior is
correct for byte aligned reads of byte aligned bitmaps.
As we removed the support of VBE modesetting that was done by GRUB early
on boot, we need to determine if we can modeset the resolution with our
drivers, and if not, we should enable text mode and ensure that
SystemServer knows about it too.
Also, SystemServer should first check if there's a framebuffer device
node, which is an indication that text mode was not even if it was
requested. Then, if it doesn't find it, it should check what boot_mode
argument the user specified (in case it's self-test). This way if we
try to use bochs-display device (which is not VGA compatible) and
request a text mode, it will not honor the request and will continue
with graphical mode.
Also try to print critical messages with mininum memory allocations
possible.
In LibVT, We make the implementation flexible for kernel-specific
methods that are implemented in ConsoleImpl class.
Previously ByteBuffer would internally hold a RefPtr to the byte
buffer and would behave like a reference type, i.e. copying a
ByteBuffer would not create a duplicate byte buffer, but rather
two objects which refer to the same internal buffer.
This also changes ByteBuffer so that it has some internal capacity
much like the Vector<T> type. Unlike Vector<T> however a byte
buffer's data may be uninitialized.
With this commit ByteBuffer makes use of the kmalloc_good_size()
API to pick an optimal allocation size for its internal buffer.
This commit replaces the former, hand-written parser with a new one that
can be generated automatically according to a state change diagram.
The new `EscapeSequenceParser` class provides a more ergonomic interface
to dealing with escape sequences. This interface has been inspired by
Alacritty's [vte library](https://github.com/alacritty/vte/).
I tried to avoid changing the application logic inside the `Terminal`
class. While this code has not been thoroughly tested, I can't find
regressions in the basic command line utilities or `vttest`.
`Terminal` now displays nicer debug messages when it encounters an
unknown escape sequence. Defensive programming and bounds checks have
been added where we access parameters, and as a result, we can now
endure 4-5 seconds of `cat /dev/urandom`. :D
We generate EscapeSequenceStateMachine.h when building the in-kernel
LibVT, and we assume that the file is already in place when the userland
library is being built. This will probably cause problems later on, but
I can't find a way to do it nicely.
By constraining two implementations, the compiler will select the best
fitting one. All this will require is duplicating the implementation and
simplifying for the `void` case.
This constraining also informs both the caller and compiler by passing
the callback parameter types as part of the constraint
(e.g.: `IterationFunction<int>`).
Some `for_each` functions in LibELF only take functions which return
`void`. This is a minimal correctness check, as it removes one way for a
function to incompletely do something.
There seems to be a possible idiom where inside a lambda, a `return;` is
the same as `continue;` in a for-loop.
This implements the macOS API malloc_good_size() which returns the
true allocation size for a given requested allocation size. This
allows us to make use of all the available memory in a malloc chunk.
For example, for a malloc request of 35 bytes our malloc would
internally use a chunk of size 64, however the remaining 29 bytes
would be unused.
Knowing the true allocation size allows us to request more usable
memory that would otherwise be wasted and make that available for
Vector, HashTable and potentially other callers in the future.
If we're constructing a FlyString from a StringView, and we already
have a matching StringImpl in the table, use HashTable::find() to
locate the existing string without creating a temporary String.
Creating a ByteBuffer involves two allocations:
-One for the ByteBufferImpl object
-Another one for the actual byte buffer
This changes the ByteBuffer and ByteBufferImpl classes
so only one allocation is necessary.
This adds an `AK::ByteReader` to help with that so we don't duplicate
the logic all over the place.
No more `*(const u16*)` and `*(const u32*)` for anyone.
This should help a little with #7060.
We call placement new for the newly added slots. However, we should
also specify an initializer so primitive data types like u64 are
initialized appropriately.
Unfortunately adopt_ref requires a reference, which obviously does not
work well with when attempting to harden against allocation failure.
The adopt_ref_if_nonnull() variant will allow you to avoid using bare
pointers, while still allowing you to handle allocation failure.
Unfortunately adopt_own requires a reference, which obviously does not
work well with when attempting to harden against allocation failure.
The adopt_own_if_nonnull() variant will allow you to avoid using bare
pointers, while still allowing you to handle allocation failure.
This patch adds two new methods to LexicalPath. LexicalPath::append
appends a new path component to a LexicalPath, and LexicalPath::join
constructs a new LexicalPath from one or more components.
Co-authored-by: Gunnar Beutner <gunnar@beutner.name>
The get_dir_entries syscall failed if the serialized form of all the
directory entries together was too large to fit in its temporary buffer.
Now the kernel uses a fixed size buffer, that is flushed to an output
buffer when it is full. If this flushing operation fails because there
is not enough space available, the syscall will return -EINVAL. That
error code is then used in userspace as a signal to allocate a larger
buffer and retry the syscall.
This allows the construction of `Variant<int, int, int>`.
While this might not seem useful, it is very useful for making variants
that contain a series of member function pointers, which I plan to use
in LibGL for glGenLists() and co.
typeid() and RTTI was a nice clutch to implement this, but let's move
away from the horrible slowness and implement variants using type
indices for faster variants.
This commit introduces the ability to parse the document catalog dict,
as well as the page tree and individual pages. Pages obviously aren't
fully parsed, as we won't care about most of the fields until we
start actually rendering PDFs.
One of the primary benefits of the PDF format is laziness. PDFs are
not meant to be parsed all at once, and the same is true for pages.
When a Document is constructed, it builds a map of page number to
object index, but it does not fetch and parse any of the pages. A page
is only parsed when a caller requests that particular page (and is
cached going forwards).
Additionally, this commit also adds an object_cast function which
logs bad casts if DEBUG_PDF is set. Additionally, utility functions
were added to ArrayObject and DictObject to get all types of objects
from the collections to avoid having to manually cast.
This can currently parse a really simple module.
Note that it cannot parse the DataCount section, and it's still missing
almost all of the instructions.
This commit also adds a 'wasm' test utility that tries to parse a given
webassembly binary file.
It currently does nothing but exit when the parse fails, but it's a
start :^)
This enables us to use keys of type NonnullRefPtr in HashMaps and
HashTables.
This commit also includes fixes in various places that used
HashMap<T, NonnullRefPtr<U>>::get() and expected to get an
Optional<NonnullRefPtr<U>> and now get an Optional<U*>.