code: plan9front

Download patch

ref: e5d9d3c049b93a6bb948aa81398b0f841f771704
parent: 36478171be59721dcc5252043fe2955cb37fc9b3
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
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",