Commit Graph

25 Commits

Author SHA1 Message Date
HP van Braam
eb948bc5a8 Fix a crash trying to save an empty AudioStream
My friends, gather around as I learned something about the C standard
that is horrifying and may keep you, dear reader, up at night.

My journey began trying to fix something entirely unrelated and not
wanting to wait for ubsan builds when changing a testcase. So me, in my
infinite naivete just built the engine with tests=yes, but
optimizations turned on.

This resulted in a segfault on "[Audio][AudioStreamWAV] Save empty file".

Well, then, I thought. Lets built with asan then and find out where this
happens! Would it surprise you, my fellow traveler, that the results
were that no such crash occurred?

Thus, to the debugger I go! Fearless, with great optimism. Where I find
that through many an indirection the crash came because, somehow,
CowData::_unref() was getting called with a _ptr set to 0x1.

This can of course only end in tears. Or segmentation faults as we try
to read an atomic variable at the somewhat inconveniently situated
address at 0xfffffffffffffff0.

So I went and looked at the likely culprit, blaming many an innocent
recent change along the way. I shall spare you the falsly accused. But
if for some reason you slept poorly last night, I can assure you that
the voodoo dolls have been put away and will not be harmed further.

So in AudioStreamWAV::get_data() we go, where we find a perfectly
reasonable function! It checks to see whether or not its data is empty,
and if it is not it will resize a temporary Vector to have data_bytes of
space, after which it will do a perfectly pedestrian memcpy() and all is
well in the world.

Or so it seems! After many an hour of despair and disassembly I, at
last, decided to look at where the data gets set! A breakthrough!
Because of the padding data is never empty! So the code always runs!

Eureka! One would think. But then, foolishly, I looked into the
get_data() function one more. My mortal enemy was staring me in the
face, laughing. Because it did not care about this. Sure, the check was
worthless but still... What are we left with.

At this point I could feel the method mocking me.

"I resize the vector to 0, I then memcpy zero bytes into it." It said,
DARING me to object to this state of affairs.

And yet, if I changed the function to check for "data_bytes" rather
than data.is_empty() no crashes.

Was this a compiler bug? Am I losing my mind? But then... I remembered
the mantra of the wise compiler druids... "It Is Not A Compiler Bug".

But what then! The bug does not happen when memory is being watched!
Valgrind agreed that while accessing the SafeRefCount at
0xfffffffffffffff0 was incredibly rude, it did not inform me of anything
else untoward happening. So I read the memcpy() manpage... nothing... I
read the the memcpy() posix spec... nothing.

Finally, in despair and because I had nothing left to lose... The ISO C
language specification. As I was reading, I could hear
AudioStreamWAV::get_data() cackling, knowing that its time was up, but
proud of the madness it caused in my soul. Knowing I would never be the
same.

The behavior is undefined if either dest or src is an invalid or null pointer.

So... Here I stand before you, a broken person. But one richer in
knowledge.

I write you this from the depths of madness in the hopes that you, dear
reader, can be spared this ordeal.

May god have mercy on our souls.

We trigger the following sequence of events:

* memcpy(null, null, 0) is UB, thus dest and src cannot be null
* we inline the calls to the ctor and dtor
* now we have a function that does something that "proves"
  dest cannot be null
* we inline cowdata::_unref() which does a null check, on something
  that the compiler just convinced itself cannot be null
* the compiler removes the dead code branch where _ptr == nullptr
* we start to do pointer arithmetic on a nullptr and get send to
  uninitialized memory.

Co-Authored-By: Jason Beckmann <jasonabeckmann@gmail.com>
2024-12-17 23:14:39 +01:00
DeeJayLSP
afd68d785b Use qoa.c and custom compress procedure 2024-12-05 13:20:09 -03:00
what-is-a-git
707f1038c3 Add runtime file loading to AudioStreamWAV 2024-12-02 20:03:53 -05:00
nikitalita
08db8edbff fix save to wav 2024-11-01 06:11:28 -05:00
Rémi Verschelde
b998cb1335
Merge pull request #96768 from DeeJayLSP/wav-end
WAV: Fix one frame overflow at the end
2024-09-12 09:25:31 +02:00
DeeJayLSP
147accdf74 WAV: Fix one frame overflow at the end 2024-09-11 21:57:14 -03:00
Rémi Verschelde
493f3edce7
Merge pull request #96572 from adamscott/fix-samples-leak
Fix leak when using audio samples instead of streams
2024-09-09 17:51:42 +02:00
Rémi Verschelde
0e307f8647
Merge pull request #96017 from DeeJayLSP/wav-vec
AudioStream(Playback)WAV: Use LocalVectors instead of pointers
2024-09-08 23:21:23 +02:00
DeeJayLSP
d5ad6dd699 AudioStream(Playback)WAV: Use LocalVectors instead of pointers 2024-09-08 02:32:59 -03:00
Adam Scott
d3ddce6b88
Fix leak when using audio samples instead of streams 2024-09-04 12:56:03 -04:00
Rémi Verschelde
77bc419071
Merge pull request #96174 from DeeJayLSP/wav-docs
WAV stream/importer: Improve compression/loop names and descriptions
2024-08-30 23:37:50 +02:00
DeeJayLSP
5a50b3a6c5 WAV stream/importer: Improve compression/loop names and descriptions 2024-08-30 16:31:57 -03:00
DeeJayLSP
703c31fb40 WAV: Add missing break on get_length() 2024-08-25 14:18:26 -03:00
DeeJayLSP
b4d44a4253 QOA: Remove unnecessary memory allocation 2024-08-24 21:39:55 -03:00
Adam Scott
52fa4f05f3
Add samples playback support 2024-06-18 11:06:31 -04:00
DeeJayLSP
97a70cbd6e Use data length on QOA checks instead of min size 2024-05-08 12:05:21 -03:00
DeeJayLSP
b9cbf2c96f Add QOA (Quite OK Audio) as a WAV compression mode 2024-05-01 19:05:14 -03:00
Thaddeus Crews
9903e6779b
Enforce template syntax typename over class 2024-03-07 22:39:09 -06:00
A Thousand Ships
d8b29efe66
Fix member names of AudioFrame to match extension 2024-02-13 15:37:09 +01:00
Ninni Pipping
71ee65dc57 Enable shadow warnings and fix raised errors 2023-05-11 16:00:59 +02:00
Rémi Verschelde
d95794ec8a
One Copyright Update to rule them all
As many open source projects have started doing it, we're removing the
current year from the copyright notice, so that we don't need to bump
it every year.

It seems like only the first year of publication is technically
relevant for copyright notices, and even that seems to be something
that many companies stopped listing altogether (in a version controlled
codebase, the commits are a much better source of date of publication
than a hardcoded copyright statement).

We also now list Godot Engine contributors first as we're collectively
the current maintainers of the project, and we clarify that the
"exclusive" copyright of the co-founders covers the timespan before
opensourcing (their further contributions are included as part of Godot
Engine contributors).

Also fixed "cf." Frenchism - it's meant as "refer to / see".
2023-01-05 13:25:55 +01:00
bruvzg
0103af1ddd
Fix MSVC warnings, rename shadowed variables, fix uninitialized values, change warnings=all to use /W4. 2022-10-07 11:32:33 +03:00
bruvzg
ea1848ce0a
Use constexpr in the conditions with template parameters and sizeofs to suppress C4127 warnings. 2022-09-29 10:38:21 +03:00
Dave Palais
0c46068af0 Change time parameters and variables to double type
Addresses #65313
2022-09-26 13:52:54 -05:00
DeeJayLSP
4889659227 Rename AudioStreamSample to a more discoverable name 2022-07-28 13:53:36 -03:00