Attached are patches to fix a number of security vulnerabilities on biosig 3.9.0 [1,2]. The numbers indicate the last 20 patches from upstream [3,4].  Only those patches relevant for these CVE's are discussed here:

The patches 0005 - 0009 are fixing:
CVE-2025-48005 <https://security-tracker.debian.org/tracker/CVE-2025-48005>
CVE-2025-52461 <https://security-tracker.debian.org/tracker/CVE-2025-52461>
CVE-2025-52581 <https://security-tracker.debian.org/tracker/CVE-2025-52581>
CVE-2025-53518 <https://security-tracker.debian.org/tracker/CVE-2025-53518>
CVE-2025-53853 <https://security-tracker.debian.org/tracker/CVE-2025-53853>
CVE-2025-54462 <https://security-tracker.debian.org/tracker/CVE-2025-54462>

Moreover, patches 0010 and 0020 are trying to address all issues in the MFER implementation, namely
CVE-2025-46411 <https://security-tracker.debian.org/tracker/CVE-2025-46411>
CVE-2025-53511 <https://security-tracker.debian.org/tracker/CVE-2025-53511>
CVE-2025-53557 <https://security-tracker.debian.org/tracker/CVE-2025-53557>
CVE-2025-54480 <https://security-tracker.debian.org/tracker/CVE-2025-54480> - CVE-2025-54494 <https://security-tracker.debian.org/tracker/CVE-2025-54494> (15 CVEs)

However, because of the (large) number of security issues in the implementation of the support for MFER format, further checks might be in order.

So, patch 0019 is guarding against unintended use of MFER. It disables support for reading MFER and disable a possible attack vector from malicious MFER data.

MFER files can be read only when environment variable
   BIOSIG_MFER_TRUST_INPUT=1
is set.  Those who rely on Biosig supporting MFER, can set that flag. However, this should only be done when the file comes from a trusted source, and it is safe to assume that there is no malicious intend.  I'm aware that the need to set this flag will come at the cost for those users who rely on MFER support. If that is affecting you in a negative way, please get in contact with me, so that we can discuss an action plan how to address this best and guarantee that the implementation for MFER support is safe to use under all conditions.

Cheers, and stay safe,

   Alois


P.S.: The attached patches should be sufficient to address debian bug #1112133 , and should be sufficient for patching biosig 3.9.0.
If you use biosig 3.9.1, only patch 0019 (and optionally 0020) are needed.


[1] https://security-tracker.debian.org/tracker/source-package/biosig
[2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1112133.
[3]  https://git.code.sf.net/p/biosig/code
[4] https://git.ista.ac.at/alois.schloegl/biosig/-/commits/master?search=CVE











From bd1ed634059db8312ce521931bb90785723e5af9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Fri, 8 Aug 2025 17:10:04 +0200
Subject: [PATCH 05/20] [b4c] fix reading ISHNE data 	fixes CVE-2025-53853
 (i.e. TALOS-2025-2232)

---
 biosig4c++/biosig.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/biosig4c++/biosig.c b/biosig4c++/biosig.c
index b35c0479..67108ea0 100644
--- a/biosig4c++/biosig.c
+++ b/biosig4c++/biosig.c
@@ -8477,19 +8477,20 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 
 		char flagANN = !strncmp((char*)hdr->AS.Header,"ANN",3);
 
-		fprintf(stderr,"Warning SOPEN(ISHNE): support for ISHNE format is experimental\n");
-
                    // unknown, generic, X,Y,Z, I-VF, V1-V6, ES, AS, AI
     	        uint16_t Table1[] = {0,0,16,17,18,1,2,87,88,89,90,3,4,5,6,7,8,131,132,133};
     	        size_t len;
     	        struct tm  t;
 
-		hdr->HeadLen = lei32p(hdr->AS.Header+22);
+		hdr->HeadLen = lei32p(hdr->AS.Header+10)+522;
                 if (count < hdr->HeadLen) {
 		    	hdr->AS.Header = (uint8_t*)realloc(hdr->AS.Header,hdr->HeadLen);
 		    	count  += ifread(hdr->AS.Header+count,1,hdr->HeadLen-count,hdr);
 		}
-		hdr->HeadLen = count;
+		if (count < hdr->HeadLen) {
+			biosigERROR(hdr, B4C_INCOMPLETE_FILE, "(ISNHE) Header larger then file - file is incomplete or unsupported");
+			return(hdr);
+		};
 
                 if (VERBOSE_LEVEL>6) {
                 	fprintf(stdout,"SOPEN(ISNHE): @%p %i\n",hdr->AS.Header,hdr->HeadLen);
@@ -8577,7 +8578,7 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 			hdr->EVENT.LenCodeDesc = 9;
 
 			uint8_t evt[4];
-			ifseek(hdr, lei32p(hdr->AS.Header+22), SEEK_SET);
+			ifseek(hdr, hdr->HeadLen, SEEK_SET);
 			size_t N = 0, pos=0;
 			while (!ifeof(hdr)) {
 				if (!ifread(evt, 1, 4, hdr)) break;
-- 
2.47.2

From 0211292419ad9f1bf9693563692548a39491dad0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Fri, 8 Aug 2025 18:13:38 +0200
Subject: [PATCH 06/20] [b4c] GDF: better sanity check of reading event table 
 fixes CVE-2025-52581 (i.e. TALOS-2025-2233)

---
 biosig4c++/biosig.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/biosig4c++/biosig.c b/biosig4c++/biosig.c
index 67108ea0..a3125824 100644
--- a/biosig4c++/biosig.c
+++ b/biosig4c++/biosig.c
@@ -3682,15 +3682,21 @@ int read_header(HDRTYPE *hdr) {
 			char flag = buf[0];
 			int sze = (flag & 2) ? 12 : 6;
 			if (flag & 4) sze+=8;
+			size_t sizeRawEVT = 8 + hdr->EVENT.N * (size_t)sze;
 
-			hdr->AS.rawEventData = (uint8_t*)realloc(hdr->AS.rawEventData,8+hdr->EVENT.N*sze);
+			void* ptr = realloc(hdr->AS.rawEventData, sizeRawEVT);
+			if (ptr==NULL) {
+                                biosigERROR(hdr, B4C_MEMORY_ALLOCATION_FAILED, "allocating memory for GDF EventTable failed");
+                                return(-3);
+			}
+			hdr->AS.rawEventData = (uint8_t*)ptr;
 			c = ifread(hdr->AS.rawEventData+8, sze, hdr->EVENT.N, hdr);
 			ifseek(hdr, hdr->HeadLen, SEEK_SET);
 			if (c < hdr->EVENT.N) {
                                 biosigERROR(hdr, B4C_INCOMPLETE_FILE, "reading GDF eventtable failed");
                                 return(-3);
 			}
-			rawEVT2hdrEVT(hdr, 8+hdr->EVENT.N*sze);
+			rawEVT2hdrEVT(hdr, sizeRawEVT);
 		}
 		else
 			hdr->EVENT.N = 0;
-- 
2.47.2

From d7d146b70b9b261b132dac7f9293271a4e8d481d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Sun, 10 Aug 2025 16:20:54 +0200
Subject: [PATCH 07/20] [b4c] ABF: better sanity checks         fixes
 CVE-2025-53518 (i.e. TALOS-2025-2231)

---
 biosig4c++/t210/sopen_abf_read.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/biosig4c++/t210/sopen_abf_read.c b/biosig4c++/t210/sopen_abf_read.c
index 410c42ca..1b9eabb7 100644
--- a/biosig4c++/t210/sopen_abf_read.c
+++ b/biosig4c++/t210/sopen_abf_read.c
@@ -538,9 +538,13 @@ EXTERN_C void sopen_abf_read(HDRTYPE* hdr) {
 		}
 
 		/* ===== EVENT TABLE ===== */
-		uint32_t n1,n2;
-		n1 = lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lActualEpisodes)) - 1;
-		n2 = lei32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumTagEntries));
+		size_t n1,n2;
+		n1 = leu32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lActualEpisodes)) - 1;
+		n2 = leu32p(hdr->AS.Header + offsetof(struct ABFFileHeader, lNumTagEntries));
+		if (0xffffffff < (n1+n2)) {
+			biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "reading ABF with more 2^32 events or more is not supported");
+			return;
+		}
 		hdr->EVENT.N = n1+n2;
 
 		/* add breaks between sweeps */
-- 
2.47.2

From 6c6be44f302156c53a1c305d54ea1705e5f9054d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Sun, 10 Aug 2025 23:06:27 +0200
Subject: [PATCH 08/20] [b4c] NEX: improve sanity check, fix event counting 
 fixes CVE-2025-52461 (i.e. TALOS-2025-2238) 	fixes CVE-2025-54462 (i.e.
 TALOS-2025-2239)

---
 biosig4c++/biosig.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/biosig4c++/biosig.c b/biosig4c++/biosig.c
index a3125824..2acce4cc 100644
--- a/biosig4c++/biosig.c
+++ b/biosig4c++/biosig.c
@@ -10113,6 +10113,7 @@ if (VERBOSE_LEVEL>2)
 			hc->Transducer[0] = 0;
 
 			size_t n;
+			size_t offset;
 			if (v==5) {
 				hc->GDFTYP = (leu32p(hdr->AS.Header + H1LEN + k*H2LEN + 92)==1) ? 16 : 3;
 				hc->PhysDimCode = PhysDimCode(hdr->AS.Header + H1LEN + k*H2LEN + 5*8 + 64);
@@ -10120,7 +10121,7 @@ if (VERBOSE_LEVEL>2)
 				hc->Cal = lef64p(hdr->AS.Header + 64+8*5+32 + H1LEN + k*H2LEN);
 				hc->Off = lef64p(hdr->AS.Header + 64+8*5+40 + H1LEN + k*H2LEN);
 				hc->SPR = leu64p(hdr->AS.Header + 64+8*5+48 + H1LEN + k*H2LEN);
-				hc->bufptr = hdr->AS.Header + leu64p(hdr->AS.Header + 64+8 + H1LEN + k*H2LEN);
+				offset  = leu64p(hdr->AS.Header + 64+8 + H1LEN + k*H2LEN);
 			}
 			else {
 				hc->GDFTYP = 3;
@@ -10129,8 +10130,13 @@ if (VERBOSE_LEVEL>2)
 				hc->Cal = lef64p(hdr->AS.Header + 64+8*4+3*8    + H1LEN + k*H2LEN);
 				hc->Off = lef64p(hdr->AS.Header + 64+8*4+3*8+20 + H1LEN + k*H2LEN);
 				hc->SPR = leu32p(hdr->AS.Header + 64+8*4+4*8    + H1LEN + k*H2LEN);
-				hc->bufptr = hdr->AS.Header+leu32p(hdr->AS.Header + 64+8 + H1LEN + k*H2LEN);
+				offset  = leu32p(hdr->AS.Header + 64+8 + H1LEN + k*H2LEN);
 			}
+			if (offset > count) {
+				biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "reading NEX failed (bufptr must point into Header Section)");
+				return(hdr);
+			}
+			hc->bufptr = hdr->AS.Header + offset;
 
 			if (VERBOSE_LEVEL>7) fprintf(stdout,"%s (line %i): VarHdr # %i %i %i %i \n",__func__,__LINE__, k,v,type,(int)n);
 
@@ -10193,8 +10199,8 @@ if (VERBOSE_LEVEL>2)
 						hdr->EVENT.CHN[N+l] = k;
 						//hdr->EVENT.TimeStamp[N+l] = 0;
 					}
+					N+=n;
 				}
-				N+=n;
 			}
 			hdr->EVENT.N=N;
 		}
-- 
2.47.2

From cc49acf59adac883e1a4fadacc3e095de091eadd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Sun, 10 Aug 2025 23:29:14 +0200
Subject: [PATCH 09/20] [b4c] RHD2000: fix case when all channels are disabled 
 fixes CVE-2025-48005 (i.e. TALOS-2025-2240)

---
 biosig4c++/t210/sopen_rhd2000_read.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/biosig4c++/t210/sopen_rhd2000_read.c b/biosig4c++/t210/sopen_rhd2000_read.c
index ecf59473..9c50cd0d 100644
--- a/biosig4c++/t210/sopen_rhd2000_read.c
+++ b/biosig4c++/t210/sopen_rhd2000_read.c
@@ -300,6 +300,9 @@ int sopen_rhs2000_read(HDRTYPE* hdr) {
 		hdr->SPR = (major == 1 ? 60 : 128);
 		size_t bi = (0+4)*hdr->SPR;
 
+		// allocate memory for time channel
+		hdr->CHANNEL = (CHANNEL_TYPE*) realloc(hdr->CHANNEL, sizeof(CHANNEL_TYPE));
+
 		// read all signal groups
 		for (int nsg=0; nsg < numberOfSignalGroups; nsg++) {
 			char SignalGroupName[101], SignalGroupPrefix[101];
-- 
2.47.2

From ba2f1c381b10f5ab50c94be3291b2560af0f7a96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Mon, 11 Aug 2025 22:36:49 +0200
Subject: [PATCH 10/20] [b4c] MFER: improve sanity checks             fixes
 CVE-2025-54480-CVE-2025-54494 (i.e. TALOS-2025-2234)             fixes
 CVE-2025-53557 (i.e. TALOS-2025-2235)             fixes CVE-2025-46411 (i.e.
 TALOS-2025-2236)             fixes CVE-2025-53511 (i.e. TALOS-2025-2237)

---
 biosig4c++/biosig.c | 148 ++++++++++++++++++++++++++++++--------------
 1 file changed, 103 insertions(+), 45 deletions(-)

diff --git a/biosig4c++/biosig.c b/biosig4c++/biosig.c
index 2acce4cc..428e1621 100644
--- a/biosig4c++/biosig.c
+++ b/biosig4c++/biosig.c
@@ -8677,6 +8677,19 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 		hdr->FILE.LittleEndian = 0;
 		hdr->SampleRate = 1000; 	// default sampling rate is 1000 Hz
 		hdr->NS = 1;	 		// default number of channels is 1
+		hdr->CHANNEL = (CHANNEL_TYPE*)realloc(hdr->CHANNEL, hdr->NS*sizeof(CHANNEL_TYPE));
+		{
+			CHANNEL_TYPE *hc = hdr->CHANNEL+0;
+			hc->SPR = 0;
+			hc->PhysDimCode = 4275;	// uV : default value in Table 5, ISO/FDIS 22077-1(E)ISO/WD 22077-1
+			hc->Cal = 1.0;
+			hc->Off = 0.0;
+			hc->OnOff = 1;
+			hc->LeadIdCode = 0;
+			hc->GDFTYP = 3;
+			hc->Transducer[0] = 0;
+			hc->Label[0] = 0;
+		}
 		/* TAG */
 		uint8_t tag = hdr->AS.Header[0];
     		ifseek(hdr,1,SEEK_SET);
@@ -8722,20 +8735,31 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 
 			/* VALUE */
 			if (tag==0) {
-				if (len!=1) fprintf(stderr,"Warning MFER tag0 incorrect length %i!=1\n",len);
+				if (len!=0) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag0 incorrect (must be 1)!");
+					return (hdr);
+				}
 				curPos += ifread(buf,1,len,hdr);
 			}
 			else if (tag==1) {
 				// Endianity
-				if (len!=1) fprintf(stderr,"Warning MFER tag1 incorrect length %i!=1\n",len);
+				if (len>1) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag1 incorrect");
+					return (hdr);
+				}
+				if (len==0) {
+					hdr->FILE.LittleEndian = 0;
+				}
+				else {
 					ifseek(hdr,len-1,SEEK_CUR);
-				curPos += ifread(buf,1,1,hdr);
-				hdr->FILE.LittleEndian = buf[0];
-#if (__BYTE_ORDER == __BIG_ENDIAN)
-				SWAP = hdr->FILE.LittleEndian;
-#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
-				SWAP = !hdr->FILE.LittleEndian;
-#endif
+					curPos += ifread(buf,1,1,hdr);
+					hdr->FILE.LittleEndian = buf[0];
+	#if (__BYTE_ORDER == __BIG_ENDIAN)
+					SWAP = hdr->FILE.LittleEndian;
+	#elif (__BYTE_ORDER == __LITTLE_ENDIAN)
+					SWAP = !hdr->FILE.LittleEndian;
+	#endif
+				}
 			}
 			else if (tag==2) {
 				// Version
@@ -8754,7 +8778,10 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: character code <%s>\n",v);
 			}
 			else if (tag==4) {
 				// SPR
-				if (len>4) fprintf(stderr,"Warning MFER tag4 incorrect length %i>4\n",len);
+				if (len>4) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag4 incorrect");
+					return (hdr);
+				}
 				curPos += ifread(buf,1,len,hdr);
 				hdr->SPR = *(int64_t*) mfer_swap8b(buf, len, SWAP);
 if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->SPR);
@@ -8762,27 +8789,37 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->SP
 			else if (tag==5)     //0x05: number of channels
 			{
 				uint16_t oldNS=hdr->NS;
-				if (len>4) fprintf(stderr,"Warning MFER tag5 incorrect length %i>4\n",len);
-				curPos += ifread(buf,1,len,hdr);
-				hdr->NS = *(int64_t*) mfer_swap8b(buf, len, SWAP);
-if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NS);
-				hdr->CHANNEL = (CHANNEL_TYPE*)realloc(hdr->CHANNEL, hdr->NS*sizeof(CHANNEL_TYPE));
-				for (k=oldNS; k<hdr->NS; k++) {
-					CHANNEL_TYPE *hc = hdr->CHANNEL+k;
-					hc->SPR = 0;
-					hc->PhysDimCode = 4275;	// uV : default value in Table 5, ISO/FDIS 22077-1(E)ISO/WD 22077-1
-					hc->Cal = 1.0;
-					hc->Off = 0.0;
-					hc->OnOff = 1;
-					hc->LeadIdCode = 0;
-					hc->GDFTYP = 3;
-					hc->Transducer[0] = 0;
+				if (len>4) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag5 incorrect");
+					return (hdr);
+				}
+				if (len==0)
+					hdr->NS = 1;
+				else {
+					curPos += ifread(buf,1,len,hdr);
+					hdr->NS = *(int64_t*) mfer_swap8b(buf, len, SWAP);
+	if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NS);
+					hdr->CHANNEL = (CHANNEL_TYPE*)realloc(hdr->CHANNEL, hdr->NS*sizeof(CHANNEL_TYPE));
+					for (k=oldNS; k<hdr->NS; k++) {
+						CHANNEL_TYPE *hc = hdr->CHANNEL+k;
+						hc->SPR = 0;
+						hc->PhysDimCode = 4275;	// uV : default value in Table 5, ISO/FDIS 22077-1(E)ISO/WD 22077-1
+						hc->Cal = 1.0;
+						hc->Off = 0.0;
+						hc->OnOff = 1;
+						hc->LeadIdCode = 0;
+						hc->GDFTYP = 3;
+						hc->Transducer[0] = 0;
+					}
 				}
 			}
 			else if (tag==6) 	// 0x06 "number of sequences"
 			{
 				// NRec
-				if (len>4) fprintf(stderr,"Warning MFER tag6 incorrect length %i>4\n",len);
+				if (len > 4) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag6 incorrect");
+					return (hdr);
+				}
 				curPos += ifread(buf,1,len,hdr);
 				hdr->NRec = *(int64_t*) mfer_swap8b(buf, len, SWAP);
 if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NRec);
@@ -8808,7 +8845,10 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NR
 			}
 			else if (tag==10) {
 				// GDFTYP
-				if (len!=1) fprintf(stderr,"warning MFER tag10 incorrect length %i!=1\n",len);
+				if (len!=1) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag10 incorrect (must be 1)!");
+					return (hdr);
+				}
 				curPos += ifread(&gdftyp,1,1,hdr);
 				if 	(gdftyp==0)	gdftyp=3; // int16
 				else if (gdftyp==1)	gdftyp=4; // uint16
@@ -8826,34 +8866,52 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NR
 			else if (tag==11)    //0x0B
 			{
 				// Fs
-				if (len>6) fprintf(stderr,"Warning MFER tag11 incorrect length %i>6\n",len);
-				double  fval;
-				curPos += ifread(buf,1,len,hdr);
-				fval = *(int64_t*) mfer_swap8b(buf+2, len-2, SWAP);
-
-				hdr->SampleRate = fval*pow(10.0, (int8_t)buf[1]);
-				if (buf[0]==1)  // s
-					hdr->SampleRate = 1.0/hdr->SampleRate;
+				if (len>6) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag11 larger 6 - not supported");
+					return (hdr);
+				}
+				if (len==0)
+					hdr->SampleRate = 1000;
+				else {
+					double  fval;
+					curPos += ifread(buf,1,len,hdr);
+					fval = *(int64_t*) mfer_swap8b(buf+2, len-2, SWAP);
 
-if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i %i %g \n",tag,len,buf[0], buf[1], hdr->SampleRate);
+					hdr->SampleRate = fval*pow(10.0, (int8_t)buf[1]);
+					if (buf[0]==1)  // s
+						hdr->SampleRate = 1.0/hdr->SampleRate;
+				}
+				if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i %i %g \n",tag,len,buf[0], buf[1], hdr->SampleRate);
 
 			}
 			else if (tag==12)    //0x0C
 			{
 				// sampling resolution
-				if (len>6) fprintf(stderr,"Warning MFER tag12 incorrect length %i>6\n",len);
-				val32   = 0;
-				int8_t  v8;
-				curPos += ifread(&UnitCode,1,1,hdr);
-				curPos += ifread(&v8,1,1,hdr);
-				curPos += ifread(buf,1,len-2,hdr);
-				Cal = *(int64_t*) mfer_swap8b(buf, len-2, SWAP);
-				Cal *= pow(10.0,v8);
+				if (len>6) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag12 larger 6 - not supported");
+					return (hdr);
+				}
+				if (len==0) {
+					Cal = 1e-6;
+					UnitCode = 0;
+				}
+				else {
+					val32 = 0;
+					int8_t v8;
+					curPos += ifread(&UnitCode,1,1,hdr);
+					curPos += ifread(&v8,1,1,hdr);
+					curPos += ifread(buf,1,len-2,hdr);
+					Cal = *(int64_t*) mfer_swap8b(buf, len-2, SWAP);
+					Cal *= pow(10.0,v8);
+				}
 				if (!MFER_PhysDimCodeTable[UnitCode])
 					fprintf(stderr,"Warning MFER: unsupported physical unit (code=%i)\n", UnitCode);
 			}
 			else if (tag==13) {
-				if (len>8) fprintf(stderr,"Warning MFER tag13 incorrect length %i>8\n",len);
+				if (len>8) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag13 larger 8 - not supported");
+					return (hdr);
+				}
 				curPos += ifread(&buf,1,len,hdr);
 				if      (gdftyp == 1) Off = ( int8_t)buf[0];
 				else if (gdftyp == 2) Off = (uint8_t)buf[0];
-- 
2.47.2

From 7d1dccb1080c7b9baf23676da4184d76f3c886b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Fri, 29 Aug 2025 16:53:20 +0200
Subject: [PATCH 19/20] [b4c] MFER: add guard against unintended and
 potentially unsafe use of MFER 	addresses CVE-2025-54480 -
 CVE-2025-54494

---
 biosig4c++/biosig.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/biosig4c++/biosig.c b/biosig4c++/biosig.c
index 428e1621..5495a37d 100644
--- a/biosig4c++/biosig.c
+++ b/biosig4c++/biosig.c
@@ -8668,6 +8668,17 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 
 		hdr->FLAG.OVERFLOWDETECTION = 0; 	// MFER does not support automated overflow and saturation detection
 
+		/* FIXME: the current implemention has a number of flaws and limitations, see
+			CVE-2025-54480 - CVE-2025-54494,
+			Some of thse might be already fixed, but further review and additional fixes might be needed
+			Only then, the following guard should be removed.
+		*/
+		char *FLAG_ENABLE_MFER = getenv("BIOSIG_MFER_TRUST_INPUT");
+		if (FLAG_ENABLE_MFER==NULL || strcmp(FLAG_ENABLE_MFER,"1") ) {
+			biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "MFER not supported unless BIOSIG_MFER_TRUST_INPUT=1 is set");
+			return (hdr);
+		}
+
 	    	uint8_t buf[128];
 		void* ptrbuf = buf;
 		uint8_t gdftyp = 3; 	// default: int16
-- 
2.47.2

From 1d9af2b1747f8fd1a632c71bc78925c38359b315 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alois=20Schl=C3=B6gl?= <[email protected]>
Date: Sun, 31 Aug 2025 21:23:02 +0200
Subject: [PATCH 20/20] [b4c] MFER: several improvements fixing some potential
 security issues 	related to CVE-2025-54480 - CVE-2025-54494

---
 biosig4c++/biosig.c | 65 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 50 insertions(+), 15 deletions(-)

diff --git a/biosig4c++/biosig.c b/biosig4c++/biosig.c
index 5495a37d..b38407e9 100644
--- a/biosig4c++/biosig.c
+++ b/biosig4c++/biosig.c
@@ -8679,7 +8679,7 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 			return (hdr);
 		}
 
-	    	uint8_t buf[128];
+		uint8_t buf[256];
 		void* ptrbuf = buf;
 		uint8_t gdftyp = 3; 	// default: int16
 		uint8_t UnitCode=0;
@@ -8746,7 +8746,7 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 
 			/* VALUE */
 			if (tag==0) {
-				if (len!=0) {
+				if (len!=1) {
 					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag0 incorrect (must be 1)!");
 					return (hdr);
 				}
@@ -8775,14 +8775,20 @@ if (VERBOSE_LEVEL > 7) fprintf(stdout,"biosig/%s (line %d): #%d label <%s>\n", _
 			else if (tag==2) {
 				// Version
 				uint8_t v[3];
-				if (len!=3) fprintf(stderr,"Warning MFER tag2 incorrect length %i!=3\n",len);
+				if (len!=3) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag2 incorrect (length must be 3) ");
+					return (hdr);
+				}
 				curPos += ifread(&v,1,3,hdr);
 				hdr->VERSION = v[0] + (v[1]<10 ? v[1]/10.0 : (v[1]<100 ? v[1]/100.0 : v[1]/1000.0));
 				}
 			else if (tag==3) {
 				// character code
 				char v[17];
-				if (len>16) fprintf(stderr,"Warning MFER tag2 incorrect length %i>16\n",len);
+				if (len>16) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag3 incorrect (length must not exceed 16) ");
+					return (hdr);
+				}
 				curPos += ifread(&v,1,len,hdr);
 				v[len]  = 0;
 if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: character code <%s>\n",v);
@@ -8801,7 +8807,7 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->SP
 			{
 				uint16_t oldNS=hdr->NS;
 				if (len>4) {
-					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag5 incorrect");
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag5 incorrect (must not exceed 4)");
 					return (hdr);
 				}
 				if (len==0)
@@ -8828,7 +8834,7 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->SP
 			{
 				// NRec
 				if (len > 4) {
-					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag6 incorrect");
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag6 incorrect (must not exceed 4)");
 					return (hdr);
 				}
 				curPos += ifread(buf,1,len,hdr);
@@ -8836,7 +8842,10 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->SP
 if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NRec);
 			}
 			else if (tag==8) {
-				if (len>2) fprintf(stderr,"Warning MFER tag8 incorrect length %i>2\n",len);
+				if (len > 2) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag8 incorrect (must not exceed 2)");
+					return (hdr);
+				}
 				curPos += ifread(buf,1,len,hdr);
 			/*	// NOT USED
 				// Type of Waveform
@@ -8915,6 +8924,10 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NR
 					Cal = *(int64_t*) mfer_swap8b(buf, len-2, SWAP);
 					Cal *= pow(10.0,v8);
 				}
+				if ( UnitCode * sizeof(MFER_PhysDimCodeTable[0]) > sizeof(MFER_PhysDimCodeTable)) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "undefined or invalid unit code");
+					return (hdr);
+				}
 				if (!MFER_PhysDimCodeTable[UnitCode])
 					fprintf(stderr,"Warning MFER: unsupported physical unit (code=%i)\n", UnitCode);
 			}
@@ -9054,7 +9067,7 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i \n",tag,len,(int)hdr->NR
 if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i %i %i %i %i %i %i\n",tag,len, chan, tag2,len2, buf[0], buf[1], (int)hdr->SPR, (int)hdr->CHANNEL[chan].SPR);
 
 					}
-					else if (tag2==9) {	//leadname
+					else if (tag2==9) {     //leadname
 						if (len2==2)
 							hdr->CHANNEL[chan].LeadIdCode = 0;
 						else if (len2==1)
@@ -9162,6 +9175,11 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i %i %i %i %i %g %i %g\n",
 			else if (tag==64)     //0x40
 			{
 				// preamble
+				if (len!=32) {
+					fprintf(stderr,"Warning MFER tag64 incorrect length %i\n",len);
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag64 invalid (must be 4+28=32)" );
+					return (hdr);
+				}
 				char tmp[256];
 				curPos += ifread(tmp,1,len,hdr);
 				if (VERBOSE_LEVEL>7) {
@@ -9173,6 +9191,10 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i %i %i %i %i %g %i %g\n",
 			else if (tag==65)     //0x41: patient event
 			{
 				// event table
+				if (len>=sizeof(buf)) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag65 too large (not supported)" );
+					return (hdr);
+				}
 
 				curPos += ifread(buf,1,len,hdr);
 				if (len>2) {
@@ -9213,8 +9235,14 @@ if (VERBOSE_LEVEL>7) fprintf(stdout,"MFER: TLV %i %i %i %i %i %i %i %g %i %g\n",
 			}
 			else if (tag==67)     //0x43: Sample skew
 			{
-				int skew=0;
-				curPos += ifread(&skew, 1, len,hdr);
+				if (len!=2) {
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag64 invalid (must be 2)" );
+					return (hdr);
+				}
+				curPos += ifread(&buf, 1, 2,hdr);
+				int skew = lei16p(&buf);
+				hdr->CHANNEL[chan].TOffset = skew * 1e-9;
+
 if (VERBOSE_LEVEL>2)
 	fprintf(stdout,"MFER: sample skew %i ns\n",skew);
 			}
@@ -9243,10 +9271,15 @@ if (VERBOSE_LEVEL>2)
 			else if (tag==130)    //0x82
 			{
 				// Patient Id
-				if (len>64) fprintf(stderr,"Warning MFER tag131 incorrect length %i>64\n",len);
+				if (len>64) {
+					fprintf(stderr,"Warning MFER tag130 incorrect length %i>64\n",len);
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag130 incorrect (must not be larger than 64) - not supported");
+					return (hdr);
+				}
 				if (len>MAX_LENGTH_PID) {
 					ifread(hdr->Patient.Id,1,MAX_LENGTH_PID,hdr);
 					ifseek(hdr,MAX_LENGTH_PID-len,SEEK_CUR);
+					hdr->Patient.Id[MAX_LENGTH_PID]=0;
 					curPos += len;
 				}
 				else
@@ -9256,7 +9289,11 @@ if (VERBOSE_LEVEL>2)
 			else if (tag==131)    //0x83
 			{
 				// Patient Age
-				if (len!=7) fprintf(stderr,"Warning MFER tag131 incorrect length %i!=7\n",len);
+				if (len!=7) {
+					fprintf(stderr,"Warning MFER tag131 incorrect length %i!=7\n",len);
+					biosigERROR(hdr, B4C_FORMAT_UNSUPPORTED, "length of MFER tag131 incorrect (must be 7) - not supported");
+					return (hdr);
+				}
 				curPos += ifread(buf,1,len,hdr);
 				uint16_t t16;
 				memcpy(&t16, buf+3, 2);
@@ -9320,9 +9357,7 @@ if (VERBOSE_LEVEL>2)
 		hdr->FLAG.OVERFLOWDETECTION = 0; 	// overflow detection OFF - not supported
 	 	hdr->AS.bpb = 0;
 	 	for (k=0; k<hdr->NS; k++) {
-
-	 		if (VERBOSE_LEVEL>8)
-	 			fprintf(stdout,"sopen(MFER): #%i\n",(int)k);
+			if (VERBOSE_LEVEL>8) fprintf(stdout,"sopen(MFER): #%i\n",(int)k);
 
 			CHANNEL_TYPE *hc = hdr->CHANNEL+k;
 			hc->Transducer[0] = 0;
-- 
2.47.2

Reply via email to