Compare commits

..
2 Commits
Author SHA1 Message Date
Illusion 1142d83adb finally understood why the use-after-free bug happened 2024-09-25 04:13:37 +02:00
Illusion f444efc5af improve the linux example 2024-09-24 23:07:49 +02:00
4 changed files with 32 additions and 33 deletions
+4 -1
View File
@@ -6,6 +6,7 @@ Files:-
Playback issues in the example program that may relate to the decoder:-
23 - Crunchy loud noise mixed with the actual audio data
uncommon/02 -> 6 channel audio might be incorrect (not a decoder issue afaik)
uncommon/04 -> We get a bits per sample mismatch
uncommon/10 -> We error with Invalid Signature. I assume for these two I should look for the frame sync bits. But maybe my decoder should reject these. idk.
uncommon/11 -> We error with Invalid Signature
@@ -34,8 +35,10 @@ Things:-
[ ] Speed optimizations
[ ] Seeking
[ ] Fuzzing to test the stability of the code
[ ] Check if the use-after-free bug happens on Windows, and if so, if the address sanitizer will show us the full stacktrace
[x] Check if the use-after-free bug happens on Windows, and if so, if the address sanitizer will show us the full stacktrace
instead of skipping some procs.
This was caused by `read_data()` and the tee reader writing into the buffer and us using some memory that was freed while the buffer
resized. Solution is to use buffer data BEFORE calling `read_data()`
[ ] Encoder (low priority for now)
+26 -21
View File
@@ -1,4 +1,4 @@
package flac_example
package flac_linux_example
import "core:fmt"
import "core:mem"
@@ -51,13 +51,13 @@ main :: proc() {
os.exit(1)
}
sample_rate := flac_data.metadata.sample_rate
// TODO: channel mapping is incorrect for anything with more than 2 channels.
channels := flac_data.metadata.channels
md5_ctx: md5.Context
md5.init(&md5_ctx)
for {
frame, err := flac.read_next_frame(reader, flac_data)
frame, err := flac.read_next_frame(reader, flac_data, allocator)
if err != nil {
if err == .EOF {
break
@@ -67,20 +67,24 @@ main :: proc() {
}
}
//if frame.sample_rate != sample_rate || frame.channels != channels {
// sample_rate = frame.sample_rate
// channels = frame.channels
// alsa_err = alsa.pcm_set_params(handle, .S16_LE, .RW_INTERLEAVED, u32(channels), sample_rate, 1, 0)
// if alsa_err < 0 {
// fmt.eprintln("Playback open error:", alsa.strerror(alsa_err))
// os.exit(1)
// }
//}
if frame.channels != channels {
// Finish playing the previous frame before changing the hw params.
alsa.pcm_drain(handle)
channels = frame.channels
alsa_err = alsa.pcm_set_params(handle, .S16_LE, .RW_INTERLEAVED, u32(channels), flac_data.metadata.sample_rate, 1, 500000)
if alsa_err < 0 {
fmt.eprintln("Playback open error:", alsa.strerror(alsa_err))
os.exit(1)
}
}
// TODO: resampling
// 8 bps audio
//converted_samples := make([]u8, len(samples))
//converted_samples := make([]u8, len(frame.samples))
//defer delete(converted_samples)
//for sample, i in samples {
//for sample, i in frame.samples {
// converted_samples[i] = u8(sample & 0xFF)
//}
@@ -102,13 +106,6 @@ main :: proc() {
flac.md5hash(&md5_ctx, flac_data.metadata.bits_per_sample, frame.samples)
}
end := time.now()
err = flac.md5sum(&md5_ctx, flac_data)
if err == .MD5_Mismatch {
fmt.println("Decoded audio data is not correct.")
os.exit(1)
}
alsa_err = alsa.pcm_drain(handle)
if alsa_err < 0 {
@@ -116,6 +113,14 @@ main :: proc() {
}
alsa.pcm_close(handle)
end := time.now()
err = flac.md5sum(&md5_ctx, flac_data)
if err == .MD5_Mismatch {
fmt.printfln("Decoded audio data is not correct. Expected MD5: %v, Got: %v", flac_data.metadata.expected_md5, flac_data.metadata.calculated_md5)
os.exit(1)
}
elapsed := time.diff(start, end)
fmt.println("Decoding took", elapsed)
}
-11
View File
@@ -591,10 +591,6 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
tee_r: io.Tee_Reader
crc_buffer: Buffer
// NOTE: using the default heap allocator here causes a use-after-free bug on files subset/05, subset/06, and subset/25
// No idea what the cause of the bug is.
//
// Resolved without understanding the root issue. See below code for a note on this.
buffer_init_allocator(&crc_buffer, 0, 128)
defer buffer_destroy(&crc_buffer)
@@ -806,13 +802,6 @@ read_next_frame :: proc(r: ^Reader, flac: ^Flac, allocator := context.allocator)
// Frame Footer
//
crc16_bytes := buffer_to_bytes(&crc_buffer)
// NOTE: The order of these two calls is important. If we're using the default heap allocator
// for crc_buffer and we call read_data before calculate_crc16 then we run into a memory bug.
// I'm still not sure the root cause of the bug but it disappears when they're in this order.
//
// In the below cases the bug doesn't happen and the order doesn't matter.
// When using the temp allocator or an arena allocator.
// When using the reader from the arguments instead of the tee reader.
calculated_frame_crc := calculate_crc16(crc16_bytes)
frame_crc := u16(read_data(r, u16be) or_return)
+2
View File
@@ -6,6 +6,7 @@ import "core:crypto/legacy/md5"
FLAC_MAGIC :: 'f' << 24 | 'L' << 16 | 'a' << 8 | 'C'
//odinfmt: disable
@(rodata)
crc8_lookup := [256]u8 {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
@@ -41,6 +42,7 @@ crc8_lookup := [256]u8 {
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3,
}
@(rodata)
crc16_lookup := [256]u16 {
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,