PR #25306 opened by Marti2203
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25306
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25306.patch
`parse_value()` in libavformat/replaygain.c skips only spaces and tabs before
it checks for a minus sign, and then parses the integer part with `strtol()`,
which also skips `\n`, `\r`, `\v` and `\f`. For a gain such as `"\r-5.5 dB"`
the sign check sees the `\r`, `strtol()` still returns -5, and the fractional
part is added with a positive sign, so the exported gain is -4.5 dB. The volume
filter with `replaygain=track` then applies the wrong gain.
```
ffmpeg -f lavfi -i sine=d=0.2 -metadata REPLAYGAIN_TRACK_GAIN=$'\r-5.5 dB'
t.flac
ffmpeg -i t.flac
Replay Gain: track gain - -4.500000, ...
```
Same for `\n` and `\v`; a leading space or tab gives -5.5 as expected. With the
patch, which skips leading whitespace with `av_isspace()` (the same set
`strtol()` skips), all of these give -5.5, and `-af volume=replaygain=track`
gives the same output as for a plain `-5.5 dB` tag.
Such a value is unusual, but tags come from the file, e.g. values edited or
converted with CRLF line endings, and the result should not depend on which
whitespace comes before the number.
The second commit adds `fate-replaygain-flac-whitespace`, which writes a FLAC
file with `REPLAYGAIN_TRACK_GAIN` set to `"\r-5.5"` from lavfi and decodes it
through `volume=replaygain=track:precision=fixed`, so no samples are needed. It
fails on master (the output matches a -4.5 dB tag) and passes with the fix. The
sample-free tests in `fate-lavf`, `fate-mov`, `fate-iamf` and
`fate-filter-volume` pass; I did not run the tests that need the FATE samples
(`fate-flac`, `fate-id3v2` and the like).
This issue was found by an LLM-Enhanced Static Analysis Engine and verified
manually.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
From cc2a22f63c5543823920ab48d613e6fdd6b568ec Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Wed, 21 Oct 2026 19:05:17 +0800
Subject: [PATCH 1/2] avformat/replaygain: skip all leading whitespace before
the sign
parse_value() skipped only spaces and tabs before checking for a minus
sign, but strtol() also skips newlines, carriage returns, vertical tabs
and form feeds. For a value like "\r-5.5 dB" the sign check saw the
'\r', the integer part was still parsed as -5 and the fractional part
was added with a positive sign, so the exported gain was -4.5 dB.
Skip all whitespace with av_isspace(), matching what strtol() skips.
Signed-off-by: Martin Mirchev <[email protected]>
---
libavformat/replaygain.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libavformat/replaygain.c b/libavformat/replaygain.c
index 910274c8273..58ea0457217 100644
--- a/libavformat/replaygain.c
+++ b/libavformat/replaygain.c
@@ -46,7 +46,8 @@ static int32_t parse_value(const char *value, int32_t min)
if (!value)
return min;
- value += strspn(value, " \t");
+ while (av_isspace(*value))
+ value++;
if (*value == '-')
sign = -1;
--
2.54.0
From f314d6a942d6a62cd7b800c885e269cb4a6256ad Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Wed, 21 Oct 2026 19:07:25 +0800
Subject: [PATCH 2/2] tests/fate/flac: add a test for ReplayGain tags with
leading whitespace
Write a FLAC file with a REPLAYGAIN_TRACK_GAIN tag of "\r-5.5" and apply
it with the volume filter. Without the previous commit the gain is
exported as -4.5 dB instead of -5.5 dB.
Signed-off-by: Martin Mirchev <[email protected]>
---
tests/fate/flac.mak | 9 +++++++++
tests/ref/fate/replaygain-flac-whitespace | 12 ++++++++++++
2 files changed, 21 insertions(+)
create mode 100644 tests/ref/fate/replaygain-flac-whitespace
diff --git a/tests/fate/flac.mak b/tests/fate/flac.mak
index 62f2126d92d..8f2c07f623c 100644
--- a/tests/fate/flac.mak
+++ b/tests/fate/flac.mak
@@ -33,4 +33,13 @@ fate-flac-%: FUZZ = 0
FATE_FLAC-$(call ENCMUX, FLAC, FLAC, PIPE_PROTOCOL) += $(FATE_FLAC)
FATE_SAMPLES_AVCONV += $(FATE_FLAC-yes)
+
+# Apply a ReplayGain tag with a leading carriage return with the volume filter.
+FATE_FLAC_FFMPEG-$(call TRANSCODE, FLAC, FLAC, LAVFI_INDEV SINE_FILTER
VOLUME_FILTER) += fate-replaygain-flac-whitespace
+fate-replaygain-flac-whitespace: CMD = transcode lavfi "sine=d=0.1" flac \
+ "-metadata REPLAYGAIN_TRACK_GAIN=$$(printf "\r-5.5")" \
+ "-af volume=replaygain=track:precision=fixed"
+
+FATE_FFMPEG += $(FATE_FLAC_FFMPEG-yes)
+
fate-flac: $(FATE_FLAC)
diff --git a/tests/ref/fate/replaygain-flac-whitespace
b/tests/ref/fate/replaygain-flac-whitespace
new file mode 100644
index 00000000000..0d2ad040f71
--- /dev/null
+++ b/tests/ref/fate/replaygain-flac-whitespace
@@ -0,0 +1,12 @@
+c2f92642138d763242366710ebf20726
*tests/data/fate/replaygain-flac-whitespace.flac
+9880 tests/data/fate/replaygain-flac-whitespace.flac
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout_name 0: mono
+0, 0, 0, 1024, 2048, 0x0040f3f9
+0, 1024, 1024, 1024, 2048, 0x3168ef42
+0, 2048, 2048, 1024, 2048, 0xfdcbffe0
+0, 3072, 3072, 1024, 2048, 0xb15205f9
+0, 4096, 4096, 314, 628, 0x5fb14194
--
2.54.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]