ref: e5d9d3c049b93a6bb948aa81398b0f841f771704
parent: 36478171be59721dcc5252043fe2955cb37fc9b3
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Wed Mar 6 18:29:10 EST 2024
libtags: sync with upstream
binary files a/sys/src/cmd/audio/libtags/437.c b/sys/src/cmd/audio/libtags/437.c differ
--- a/sys/src/cmd/audio/libtags/8859.c
+++ b/sys/src/cmd/audio/libtags/8859.c
@@ -2,11 +2,15 @@
#include "tagspriv.h"
int
-iso88591toutf8(uchar *o, int osz, const uchar *s, int sz)
+iso88591toutf8(uchar *o0, int osz, const uchar *s, int sz)
{
+ uchar *o;
int i;
+ o = o0;
for(i = 0; i < sz && osz > 1 && s[i] != 0; i++){
+ if(s[i] >= 0x7f && s[i] <= 0x9f) /* not expecting control chars */
+ goto asis;
if(s[i] >= 0xa0 && osz < 3)
break;
@@ -26,4 +30,12 @@
*o = 0;
return i;
+
+asis:
+ /* FIXME - copy within UTF-8 chars boundaries */
+ if(sz >= osz)
+ sz = osz-1;
+ memmove(o0, s, sz);
+ o0[sz] = 0;
+ return sz;
}
--- a/sys/src/cmd/audio/libtags/flac.c
+++ b/sys/src/cmd/audio/libtags/flac.c
@@ -32,7 +32,8 @@
if(ctx->read(ctx, d, 4) != 4)
return -1;
- sz = beu3(&d[1]);
+ if((sz = beu3(&d[1])) < 0)
+ return -1;
if((d[0] & 0x80) != 0)
last = 1;
@@ -40,12 +41,12 @@
int n, offset;
char *mime;
- if(sz < 16 || ctx->read(ctx, d, 8) != 8) /* type, mime length */
+ if(sz < 8+4+20 || ctx->read(ctx, d, 8) != 8) /* type, mime length */
return -1;
sz -= 8;
n = beuint(&d[4]);
mime = ctx->buf+20;
- if(n >= sz || n >= ctx->bufsz-20 || ctx->read(ctx, mime, n) != n)
+ if(n < 0 || n >= sz-4-20 || n >= ctx->bufsz-20 || ctx->read(ctx, mime, n) != n)
return -1;
sz -= n;
mime[n] = 0;
@@ -54,8 +55,10 @@
offset = beuint(d) + ctx->seek(ctx, 0, 1) + 20;
ctx->read(ctx, d, 20);
sz -= 20;
- n = beuint(&d[16]);
- tagscallcb(ctx, Timage, "", mime, offset, n, nil);
+ if((n = beuint(&d[16])) < 0)
+ return -1;
+ if(n > 0)
+ tagscallcb(ctx, Timage, "", mime, offset, n, nil);
if(ctx->seek(ctx, sz, 1) <= 0)
return -1;
}else if((d[0] & 0x7f) == 4){ /* 4 = vorbis comment */
@@ -80,11 +83,11 @@
return -1;
tagsz = leuint(d);
sz -= 4;
- if(tagsz > sz)
+ if(tagsz < 0 || tagsz > sz)
return -1;
/* if it doesn't fit, ignore it */
- if(tagsz+1 > ctx->bufsz){
+ if(tagsz == 0 || tagsz >= ctx->bufsz){
if(ctx->seek(ctx, tagsz, 1) < 0)
return -1;
continue;
--- a/sys/src/cmd/audio/libtags/id3v2.c
+++ b/sys/src/cmd/audio/libtags/id3v2.c
@@ -164,7 +164,8 @@
f = unsync ? unsyncread : nil;
if(strcmp((char*)d, "APIC") == 0){
offset = ctx->seek(ctx, 0, 1);
- if((n = ctx->read(ctx, tag, 256)) == 256){ /* APIC mime and description should fit */
+ if((n = ctx->read(ctx, tag, 255)) == 255){ /* APIC mime and description should fit */
+ tag[255] = 0;
b = tag + 1; /* mime type */
for(n = 1 + strlen(b) + 2; n < 253; n++){
if(tag[0] == 0 || tag[0] == 3){ /* one zero byte */
@@ -195,7 +196,8 @@
break;
}
}
- tagscallcb(ctx, Timage, "PIC", strcmp(b, "JPG") == 0 ? "image/jpeg" : "image/png", offset+n, tsz-n, f);
+ if(tsz > n)
+ tagscallcb(ctx, Timage, "PIC", strcmp(b, "JPG") == 0 ? "image/jpeg" : "image/png", offset+n, tsz-n, f);
n = 256;
}
}else if(strcmp((char*)d, "RVA2") == 0 && tsz >= 6+5){
@@ -212,7 +214,9 @@
{
char *b, *tag;
- if(ctx->bufsz >= tsz+1){
+ if(tsz < 0)
+ return -1;
+ if(ctx->bufsz > tsz){
/* place the data at the end to make best effort at charset conversion */
tag = &ctx->buf[ctx->bufsz - tsz - 1];
if(ctx->read(ctx, tag, tsz) != tsz)
@@ -304,7 +308,7 @@
uint x;
int xversion, xlayer, xbitrate, i;
- if(ctx->read(ctx, ctx->buf, 256) != 256)
+ if(ctx->duration != 0 || ctx->read(ctx, ctx->buf, 256) != 256)
return;
x = beuint((uchar*)ctx->buf);
@@ -372,8 +376,8 @@
{
int sz, exsz, framesz;
int ver, unsync, offset;
- int oldpos, newpos;
- uchar d[10], *b;
+ int newpos, oldpos;
+ uchar d[10], *b, *e;
if(ctx->read(ctx, d, sizeof(d)) != sizeof(d))
return -1;
@@ -403,7 +407,7 @@
if(ctx->read(ctx, d, 4) != 4)
return -1;
exsz = (ver >= 3) ? beuint(d) : synchsafe(d);
- if(ctx->seek(ctx, exsz, 1) < 0)
+ if(exsz < 6 || ctx->seek(ctx, exsz-4, 1) < 0)
return -1;
sz -= exsz;
}
@@ -454,6 +458,7 @@
offset = ctx->seek(ctx, sz, 1);
sz = ctx->bufsz <= 2048 ? ctx->bufsz : 2048;
+ e = (uchar*)ctx->buf + sz - 3;
b = nil;
for(exsz = 0; exsz < 2048; exsz += sz){
if(ctx->read(ctx, ctx->buf, sz) != sz)
@@ -462,12 +467,12 @@
newpos = ctx->seek(ctx, (char*)b - ctx->buf + offset + exsz, 0);
if(ctx->read(ctx, d, sizeof(d)) != sizeof(d))
return 0;
- if(isid3(d) && newpos != oldpos){
+ if(isid3(d) && newpos > oldpos){
oldpos = newpos;
goto header;
}
}
- for(b = (uchar*)ctx->buf; (b = memchr(b, 0xff, sz-3)) != nil; b++){
+ for(b = (uchar*)ctx->buf; b < e && (b = memchr(b, 0xff, e-b)) != nil; b++){
if((b[1] & 0xe0) == 0xe0){
offset = ctx->seek(ctx, (char*)b - ctx->buf + offset + exsz, 0);
exsz = 2048;
--- a/sys/src/cmd/audio/libtags/m4a.c
+++ b/sys/src/cmd/audio/libtags/m4a.c
@@ -124,7 +124,7 @@
if(type < 0)
continue;
- if(ctx->seek(ctx, 8, 1) < 0) /* skip size and "data" */
+ if(sz < 16 || ctx->seek(ctx, 8, 1) < 0) /* skip size and "data" */
return -1;
sz -= 8;
if(ctx->read(ctx, d, 8) != 8) /* read data type and 4 bytes of whatever else */
@@ -148,7 +148,7 @@
}else if(dtype == 1){ /* text */
if(sz >= ctx->bufsz) /* skip tags that can't fit into memory. ">=" because of '\0' */
continue;
- if(ctx->read(ctx, d, sz) != sz)
+ if(sz < 0 || ctx->read(ctx, d, sz) != sz)
return -1;
d[sz] = 0;
txtcb(ctx, type, "", d);
--- a/sys/src/cmd/audio/libtags/mod.c
+++ b/sys/src/cmd/audio/libtags/mod.c
@@ -16,6 +16,9 @@
"CD81",
"OCTA",
"OKTA",
+ "4CHN",
+ "6CHN",
+ "8CHN",
"10CH",
"16CN",
"32CN",
@@ -42,7 +45,7 @@
return -1;
if(ctx->read(ctx, d, 20) != 20)
return -1;
- if(iso88591toutf8(o, sizeof(o), d, 20) > 0)
+ if(cp437toutf8(o, sizeof(o), d, 20) > 0)
txtcb(ctx, Ttitle, "", o);
return 0;
--- a/sys/src/cmd/audio/libtags/opus.c
+++ b/sys/src/cmd/audio/libtags/opus.c
@@ -17,7 +17,7 @@
/* calculate the size of the packet */
nsegs = d[26];
- if(ctx->read(ctx, d, nsegs+8) != nsegs+8)
+ if(nsegs > ctx->bufsz-8 || ctx->read(ctx, d, nsegs+8) != nsegs+8)
return -1;
for(sz = i = 0; i < nsegs; sz += d[i++]);
--- a/sys/src/cmd/audio/libtags/s3m.c
+++ b/sys/src/cmd/audio/libtags/s3m.c
@@ -3,7 +3,7 @@
int
tags3m(Tagctx *ctx)
{
- char d[28+1+1], o[28*UTFmax+1], *s;
+ uchar d[28+1+1], o[28*UTFmax+1], *s;
if(ctx->read(ctx, d, 28+1+1) != 28+1+1 || (d[28] != 0x1a && d[28] != 0) || d[29] != 0x10)
return -1;
--- a/sys/src/cmd/audio/libtags/tags.c
+++ b/sys/src/cmd/audio/libtags/tags.c
@@ -8,23 +8,11 @@
int format;
};
-extern int tagflac(Tagctx *ctx);
-extern int tagid3v1(Tagctx *ctx);
-extern int tagid3v2(Tagctx *ctx);
-extern int tagit(Tagctx *ctx);
-extern int tagm4a(Tagctx *ctx);
-extern int tagopus(Tagctx *ctx);
-extern int tags3m(Tagctx *ctx);
-extern int tagvorbis(Tagctx *ctx);
-extern int tagwav(Tagctx *ctx);
-extern int tagxm(Tagctx *ctx);
-extern int tagmod(Tagctx *ctx);
-
static const Getter g[] =
{
{tagid3v2, Fmp3},
{tagid3v1, Fmp3},
- {tagvorbis, Fogg},
+ {tagvorbis, Fvorbis},
{tagflac, Fflac},
{tagm4a, Fm4a},
{tagopus, Fopus},
--- a/sys/src/cmd/audio/libtags/tags.h
+++ b/sys/src/cmd/audio/libtags/tags.h
@@ -12,9 +12,9 @@
Ttitle,
Tdate, /* "2014", "2015/02/01", but the year goes first */
Ttrack, /* "1", "01", "1/4", but the track number goes first */
- Talbumgain,
+ Talbumgain, /* see GAIN note */
Talbumpeak,
- Ttrackgain,
+ Ttrackgain, /* see GAIN note */
Ttrackpeak,
Tgenre,
Timage,
@@ -22,12 +22,22 @@
Tcomment,
};
+/* GAIN note:
+ *
+ * Even though the gain value may be expected to look as "52 dB", it
+ * very well may be a plain integer (such as "12032") for R128_* tags.
+ * To do things correctly you will have to check 'const char *k' argument
+ * passed into your callback and parse it accordingly.
+ *
+ * FIXME the output gain (opus) is not parsed, btw.
+ */
+
/* Format of the audio file. */
enum
{
Funknown = -1,
Fmp3,
- Fogg,
+ Fvorbis,
Fflac,
Fm4a,
Fopus,
@@ -78,7 +88,7 @@
int samplerate; /* Hz */
int bitrate; /* Bitrate, bits/s. */
int duration; /* ms */
- int format; /* Fmp3, Fogg, Fflac, Fm4a */
+ int format; /* Fmp3, Fvorbis, Fflac, Fm4a */
/* Private, don't touch. */
int found;
--- a/sys/src/cmd/audio/libtags/tagspriv.h
+++ b/sys/src/cmd/audio/libtags/tagspriv.h
@@ -30,7 +30,7 @@
/*
* Same as utf16to8, but CP437 to UTF-8.
*/
-int cp437toutf8(char *o, int osz, const char *s, int sz);
+int cp437toutf8(uchar *o, int osz, const uchar *s, int sz);
/*
* This one is common for both vorbis.c and flac.c
@@ -42,3 +42,15 @@
void tagscallcb(Tagctx *ctx, int type, const char *k, char *s, int offset, int size, Tagread f);
#define txtcb(ctx, type, k, s) tagscallcb(ctx, type, k, (char*)s, 0, 0, nil)
+
+int tagflac(Tagctx *ctx);
+int tagid3v1(Tagctx *ctx);
+int tagid3v2(Tagctx *ctx);
+int tagit(Tagctx *ctx);
+int tagm4a(Tagctx *ctx);
+int tagopus(Tagctx *ctx);
+int tags3m(Tagctx *ctx);
+int tagvorbis(Tagctx *ctx);
+int tagwav(Tagctx *ctx);
+int tagxm(Tagctx *ctx);
+int tagmod(Tagctx *ctx);
--- a/sys/src/cmd/audio/libtags/wav.c
+++ b/sys/src/cmd/audio/libtags/wav.c
@@ -20,9 +20,7 @@
tagwav(Tagctx *ctx)
{
uchar *d;
- int i, n, info;
- u32int csz, x;
- uvlong sz;
+ int i, n, info, csz, x, sz;
d = (uchar*)ctx->buf;
@@ -49,7 +47,7 @@
break;
sz -= 4+4;
csz = leuint(d+4);
- if(sz < csz)
+ if(sz < csz || csz < 0)
break;
sz -= csz;
@@ -66,12 +64,14 @@
return -1;
ctx->duration = sz*1000 / x;
}else if(memcmp(d, "LIST", 4) == 0){
+ if(csz < 4)
+ return -1;
sz = csz - 4;
continue;
- }else if(info && csz < (u32int)ctx->bufsz){
+ }else if(info && csz < ctx->bufsz-5){
for(n = 0; n < nelem(t); n++){
if(memcmp(d, t[n].s, 4) == 0 || t[n].type == Tunknown){
- if(ctx->read(ctx, d+5, csz) != (int)csz)
+ if(ctx->read(ctx, d+5, csz) != csz)
return -1;
d[4] = 0;
d[5+csz] = 0;
@@ -87,6 +87,10 @@
if(ctx->seek(ctx, csz, 1) < 0)
return -1;
}
+
+ /* some software may append an id3v2 tag */
+ if(i > 0 && ctx->read(ctx, d, 8) == 8 && memcmp(d, "id3 ", 4) == 0)
+ tagid3v2(ctx);
return i > 0 ? 0 : -1;
}
--- a/sys/src/cmd/audio/libtags/xm.c
+++ b/sys/src/cmd/audio/libtags/xm.c
@@ -3,9 +3,9 @@
int
tagxm(Tagctx *ctx)
{
- char d[17+20+1], o[20*UTFmax+1];
+ uchar d[17+20+1], o[20*UTFmax+1];
- if(ctx->read(ctx, d, 17+20) != 17+20 || cistrncmp(d, "Extended Module: ", 17) != 0)
+ if(ctx->read(ctx, d, 17+20) != 17+20 || cistrncmp((char*)d, "Extended Module: ", 17) != 0)
return -1;
d[17+20] = 0;
if(cp437toutf8(o, sizeof(o), d+17, 20) > 0)
--- a/sys/src/cmd/audio/zuke/mkplist.c
+++ b/sys/src/cmd/audio/zuke/mkplist.c
@@ -34,7 +34,7 @@
static char *fmts[] =
{
[Fmp3] = "mp3",
- [Fogg] = "ogg",
+ [Fvorbis] = "ogg",
[Fflac] = "flac",
[Fm4a] = "m4a",
[Fopus] = "opus",