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