diff mbox series

package/libmodplug: add a patch fixing cctype UB

Message ID 20230109220041.33943-1-glex.spb@gmail.com
State Accepted
Headers show
Series package/libmodplug: add a patch fixing cctype UB | expand

Commit Message

Gleb Mazovetskiy Jan. 9, 2023, 10 p.m. UTC
libmodplug calls `cctype` functions, such as `isspace`,
with negative values. This is undefined behaviour.

While glibc allows it, it crashes on uClibc compiled
without `UCLIBC_HAS_CTYPE_SIGNED`.

Adds a patch that resolves the issue.

Also sent upstream. However, the library author has not merged
any pull request for about a year.
https://github.com/Konstanty/libmodplug/pull/92

Signed-off-by: Gleb Mazovetskiy <glex.spb@gmail.com>
---
 package/libmodplug/0001-fix-cctype-ub.patch | 954 ++++++++++++++++++++
 1 file changed, 954 insertions(+)
 create mode 100644 package/libmodplug/0001-fix-cctype-ub.patch

Comments

Yann E. MORIN Oct. 1, 2023, 7:49 p.m. UTC | #1
Gleb, All,

Sorry for the delay, now I've handled that patch...

On 2023-01-09 22:00 +0000, Gleb Mazovetskiy spake thusly:
> libmodplug calls `cctype` functions, such as `isspace`,
> with negative values. This is undefined behaviour.
> 
> While glibc allows it, it crashes on uClibc compiled
> without `UCLIBC_HAS_CTYPE_SIGNED`.
> 
> Adds a patch that resolves the issue.

We discussed it during the hackathon this WE, and we were a bit ,eh
about that patch, because it is a bit big, and upstream has not
responded to it.

However, upstream does indeed look pretty dead with no activity in the
past two years and only the occasional commit before that, so there is
very low risk at integrating this patch in Buildroot, as it should not
cause much maintenance issue. On the off chance upstream ever release
something new, we can assess the situation then.

> Also sent upstream. However, the library author has not merged
> any pull request for about a year.
> https://github.com/Konstanty/libmodplug/pull/92
> 
> Signed-off-by: Gleb Mazovetskiy <glex.spb@gmail.com>

    $ make check-package
    package/libmodplug/0001-fix-cctype-ub.patch:0: missing Signed-off-by in the header (http://nightly.buildroot.org/#_format_and_licensing_of_the_package_patches)
    package/libmodplug/0001-fix-cctype-ub.patch:0: missing Upstream in the header (http://nightly.buildroot.org/#_additional_patch_documentation)

The latter is newer than your patch, so that's not your fault; I fixed
it when applying.

For the former, since your SoB-ed your Buildoot contribution, I
copy-pasted it to the bundled patch too.

Applied to master with that fixed, thanks.

Eh, btw: I'm surprised people are still doing MOD nowadays! :-)

Regards,
Yann E. MORIN.

> ---
>  package/libmodplug/0001-fix-cctype-ub.patch | 954 ++++++++++++++++++++
>  1 file changed, 954 insertions(+)
>  create mode 100644 package/libmodplug/0001-fix-cctype-ub.patch
> 
> diff --git a/package/libmodplug/0001-fix-cctype-ub.patch b/package/libmodplug/0001-fix-cctype-ub.patch
> new file mode 100644
> index 0000000000..15e7d364e5
> --- /dev/null
> +++ b/package/libmodplug/0001-fix-cctype-ub.patch
> @@ -0,0 +1,954 @@
> +From dc6d5994b4912cb00d0d183b400edfd656d6530c Mon Sep 17 00:00:00 2001
> +From: Gleb Mazovetskiy <glex.spb@gmail.com>
> +Date: Wed, 21 Dec 2022 11:44:27 +0000
> +Subject: [PATCH] Fix UB when calling cctype functions
> +
> +Calling cctype functions, such as isspace, with negative values
> +is undefined behaviour.
> +
> +While glibc allows it, it crashes on uClibc compiled without
> +`UCLIBC_HAS_CTYPE_SIGNED`.
> +
> +Fixes the undefined behaviour by casting all arguments to
> +cctype functions to `unsigned char`.
> +---
> + src/load_abc.cpp | 284 +++++++++++++++++++++++------------------------
> + src/load_mid.cpp |   2 +-
> + src/load_pat.cpp |  30 ++---
> + 3 files changed, 158 insertions(+), 158 deletions(-)
> +
> +diff --git a/src/load_abc.cpp b/src/load_abc.cpp
> +index b45f972f..8444bd87 100644
> +--- a/src/load_abc.cpp
> ++++ b/src/load_abc.cpp
> +@@ -260,13 +260,13 @@ static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime);
> + static int abc_patno(ABCHANDLE *h, uint32_t tracktime);
> + 
> + 
> +-static int abc_isvalidchar(char c) {
> ++static int abc_isvalidchar(unsigned char c) {
> + 	return(isalpha(c) || isdigit(c) || isspace(c) || c == '%' || c == ':');
> + }
> + #if 0
> + static const char *abc_skipspace(const char *p)
> + {
> +-	while (*p && isspace(*p))
> ++	while (*p && isspace(static_cast<unsigned char>(*p)))
> + 		p++;
> + 	return p;
> + }
> +@@ -275,7 +275,7 @@ static const char *abc_skipspace(const char *p)
> + static void abc_extractkeyvalue(char *key, size_t key_max,
> + 								char *value, size_t value_max, const char *src)
> + {
> +-	while (*src && isspace(*src))
> ++	while (*src && isspace(static_cast<unsigned char>(*src)))
> + 		src++;
> + 
> + 	size_t key_size;
> +@@ -286,17 +286,17 @@ static void abc_extractkeyvalue(char *key, size_t key_max,
> + 		}
> + 		key[key_size++] = *src++;
> + 	}
> +-	while (key_size > 0 && isspace(key[key_size - 1]))
> ++	while (key_size > 0 && isspace(static_cast<unsigned char>(key[key_size - 1])))
> + 		key_size--;
> + 	key[key_size] = '\0';
> + 
> +-	while (*src && isspace(*src))
> ++	while (*src && isspace(static_cast<unsigned char>(*src)))
> + 		src++;
> + 
> + 	size_t value_size;
> + 	for (value_size = 0; value_size < value_max - 1 && *src;)
> + 		value[value_size++] = *src++;
> +-	while (value_size > 0 && isspace(value[value_size - 1]))
> ++	while (value_size > 0 && isspace(static_cast<unsigned char>(value[value_size - 1])))
> + 		value_size--;
> + 	value[value_size] = '\0';
> + 
> +@@ -359,7 +359,7 @@ static void abc_dumptracks(ABCHANDLE *h, const char *p)
> + 					nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordnote]];
> + 					nn[1] = "b # #  # # #  # #  # # # #"[e->par[chordnote]];
> + 					nn[2] = '\0';
> +-					if( isspace(nn[1]) ) nn[1] = '\0';
> ++					if( isspace(static_cast<unsigned char>(nn[1])) ) nn[1] = '\0';
> + 					printf("CMD %c: gchord %s%s",
> + 					       (char)(e->cmd), nn, chordname[e->par[chordnum]]);
> + 					if( e->par[chordbase] != e->par[chordnote] ) {
> +@@ -557,7 +557,7 @@ static void abc_new_umacro(ABCHANDLE *h, const char *m)
> + 	ABCMACRO *retval, *mp;
> + 	char key[256], value[256];
> + 	abc_extractkeyvalue(key, sizeof(key), value, sizeof(value), m);
> +-	if( strlen(key) > 1 || strchr("~HIJKLMNOPQRSTUVWXY",toupper(key[0])) == 0 ) return;
> ++	if( strlen(key) > 1 || strchr("~HIJKLMNOPQRSTUVWXY",toupper(static_cast<unsigned char>(key[0]))) == 0 ) return;
> + 	while( char *q = strchr(key, '!') )
> + 		*q = '+'; // translate oldstyle to newstyle
> + 	if( !strcmp(key,"+nil+") ) { // delete a macro
> +@@ -823,7 +823,7 @@ static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos)
> + 	char vc[21];
> + 	int i, trans=0, voiceno=0, instrno = 1, channo = 0;
> + 	for( ; *voice == ' '; voice++ ) ;	// skip leading spaces
> +-	for( i=0; i+1 < (int) sizeof(vc) && *voice && *voice != ']' && *voice != '%' && !isspace(*voice); voice++ )	// can work with inline voice instructions
> ++	for( i=0; i+1 < (int) sizeof(vc) && *voice && *voice != ']' && *voice != '%' && !isspace(static_cast<unsigned char>(*voice)); voice++ )	// can work with inline voice instructions
> + 		vc[i++] = *voice;
> + 	vc[i] = '\0';
> + 	prev = NULL;
> +@@ -1250,32 +1250,32 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim
> + 	switch(ch) {
> + 		case '^':
> + 			if( p[0] == '^' ) {
> +-				n = p[1];
> ++				n = static_cast<unsigned char>(p[1]);
> + 				i = 2;
> + 				ch = 'x';
> + 			}
> + 			else {
> +-				n = p[0];
> ++				n = static_cast<unsigned char>(p[0]);
> + 				i = 1;
> + 			}
> + 			break;
> + 		case '_':
> + 			if( p[0] == '_' ) {
> +-				n = p[1];
> ++				n = static_cast<unsigned char>(p[1]);
> + 				i = 2;
> + 				ch = 'b';
> + 			}
> + 			else {
> +-				n = p[0];
> ++				n = static_cast<unsigned char>(p[0]);
> + 				i = 1;
> + 			}
> + 			break;
> + 		case '=':
> +-			n = p[0];
> ++			n = static_cast<unsigned char>(p[0]);
> + 			i = 1;
> + 			break;
> + 		default:
> +-			n = ch;
> ++			n = static_cast<unsigned char>(ch);
> + 			i = 0;
> + 			break;
> + 	}
> +@@ -1332,7 +1332,7 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim
> + 	}
> + 	else
> + 		d[note] = 0; // someone has doen ^X3 or something like it...
> +-	while( p[i] && strchr(",'",p[i]) ) {
> ++	while( p[i] && strchr(",'",static_cast<unsigned char>(p[i])) ) {
> + 		if( p[i]==',' ) oct--;
> + 		else oct++;
> + 		i++;
> +@@ -1381,7 +1381,7 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim
> + 			}
> + 		}
> + 		tp->tienote->tiednote = 1; // mark him for the pattern writers
> +-		for( j=i; isdigit(p[j]) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too
> ++		for( j=i; isdigit(static_cast<unsigned char>(p[j])) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too
> + 		if( p[j] != '-' ) // is this note tied too?
> + 			tp->tienote = NULL; // if not the tie ends here...
> + 		return i;
> +@@ -1603,7 +1603,7 @@ static int abc_getnumber(const char *p, int *number)
> + 	int i,h;
> + 	i = 0;
> + 	h = 0;
> +-	while( isdigit(p[i]) ) {
> ++	while( isdigit(static_cast<unsigned char>(p[i])) ) {
> + 		if (i < 9)
> + 			h = 10 * h + p[i] - '0';
> + 		i++;
> +@@ -1619,7 +1619,7 @@ static int abc_getexpr(const char *p, int *number)
> + {
> + 	int i, term, total;
> + 	i = 0;
> +-	while( isspace(p[i]) )
> ++	while( isspace(static_cast<unsigned char>(p[i])) )
> + 		i++;
> + 	if( p[i] == '(' ) {
> + 		i += abc_getexpr(p+i+1, number);
> +@@ -1628,12 +1628,12 @@ static int abc_getexpr(const char *p, int *number)
> + 		return i;
> + 		}
> + 	i += abc_getnumber(p+i, &total);
> +-	while( isspace(p[i]) )
> ++	while( isspace(static_cast<unsigned char>(p[i])) )
> + 		i++;
> + 	while( p[i] == '+' ) {
> + 		i += 1 + abc_getexpr(p+i+1, &term);
> + 		total += term;
> +-		while( isspace(p[i]) )
> ++		while( isspace(static_cast<unsigned char>(p[i])) )
> + 			i++;
> + 	}
> + 	*number = total;
> +@@ -1649,7 +1649,7 @@ static int abc_notelen(const char *p, int *len, int *div)
> + 		h *= 2;
> + 		i++;
> + 	}
> +-	if( isdigit(p[i]) ) {
> ++	if( isdigit(static_cast<unsigned char>(p[i])) ) {
> + 		h /= 2;
> + 		i += abc_getnumber(p+i,&k);
> + 	}
> +@@ -1738,7 +1738,7 @@ static int abc_extract_tempo(const char *p, int invoice)
> + 				case '=':
> + 					break;
> + 				default:
> +-					if( isdigit(*q) ) {
> ++					if( isdigit(static_cast<unsigned char>(*q)) ) {
> + 						if( state ) {
> + 							q+=abc_getnumber(q,&nd1)-1;
> + 							state = 0;
> +@@ -1812,10 +1812,10 @@ static void	abc_set_parts(char **d, char *p)
> + 	j=0;
> + 	k=0;
> + 	for( i=0; p[i] && p[i] != '%'; i++ ) {
> +-		if( isupper(p[i]) ) {
> ++		if( isupper(static_cast<unsigned char>(p[i])) ) {
> + 			j++;
> + 		}
> +-		if( isdigit(p[i]) ) {
> ++		if( isdigit(static_cast<unsigned char>(p[i])) ) {
> + 			n=abc_getnumber(p+i, &k);
> + 			if( k == 0 )
> + 				k = 1;
> +@@ -1833,7 +1833,7 @@ static void	abc_set_parts(char **d, char *p)
> + 	// now copy bytes from p to *d, taking parens and digits in account
> + 	j = 0;
> + 	for( i=0; p[i] && p[i] != '%' && j < size && i < (int)size; i++ ) {
> +-		if( isdigit(p[i]) || isupper(p[i]) || p[i] == '(' || p[i] == ')' ) {
> ++		if( isdigit(static_cast<unsigned char>(p[i])) || isupper(static_cast<unsigned char>(p[i])) || p[i] == '(' || p[i] == ')' ) {
> + 			if( p[i] == ')' ) {
> + 				for( n=j; n > 0 && q[n-1] != '('; n-- )	;	// find open paren in q
> + 				// q[n+1] to q[j] contains the substring that must be repeated
> +@@ -1856,7 +1856,7 @@ static void	abc_set_parts(char **d, char *p)
> + 				}
> + 				continue;
> + 			}
> +-			if( isdigit(p[i]) ) {
> ++			if( isdigit(static_cast<unsigned char>(p[i])) ) {
> + 				n = abc_getnumber(p+i,&k);
> + 				i += n - 1;
> + 				// if nothing is ready to 'repeat', skip it.
> +@@ -2243,7 +2243,7 @@ static void abc_preprocess(ABCHANDLE *h, ABCMACRO *m)
> + 			char *p = s;
> + 			for( j=0; j<l; j++ ) {
> + 				a = m->subst[j];
> +-				if( a > 'g' && islower(a) ) {
> ++				if( a > 'g' && islower(static_cast<unsigned char>(a)) ) {
> + 					b = a - 'n';
> + 					a = "CDEFGABCDEFGABcdefgabcdefgabcdefgab"[i+b+7];
> + 					*p++ = a;
> +@@ -2339,11 +2339,11 @@ BOOL CSoundFile::TestABC(const BYTE *lpStream, DWORD dwMemLength)
> + 		}
> + 		if(id[0]=='K'
> + 			&& id[1]==':'
> +-			&& (isalpha(id[2]) || isspace(id[2])) ) return 1;
> ++			&& (isalpha(static_cast<unsigned char>(id[2])) || isspace(static_cast<unsigned char>(id[2]))) ) return 1;
> + 		// disable binary error if have any "tag"
> + 		if((id[0]>='A' && id[0]<='Z')
> + 			&& id[1]==':'
> +-			&& (isalpha(id[2]) || isspace(id[2])) ) hasText = 1;
> ++			&& (isalpha(static_cast<unsigned char>(id[2])) || isspace(static_cast<unsigned char>(id[2]))) ) hasText = 1;
> + 	}
> + 	return 0;
> + }
> +@@ -2367,7 +2367,7 @@ static ABCHANDLE *ABC_Init(void)
> + 	retval->barticks    = 0;
> + 	p = getenv(ABC_ENV_NORANDOMPICK);
> + 	if( p ) {
> +-		if( isdigit(*p) )
> ++		if( isdigit(static_cast<unsigned char>(*p)) )
> + 			retval->pickrandom = atoi(p);
> + 		if( *p == '-' ) {
> + 			retval->pickrandom = atoi(p+1)-1; // xmms preloads the file
> +@@ -2652,12 +2652,12 @@ static int ABC_Key(const char *p)
> + 	int i,j;
> + 	char c[8];
> + 	const char *q;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	q = p;
> + 	memset(c, 0, 8);
> + 	for( i=0; i<8 && *p && *p != ']'; p++ ) {
> +-		if( isspace(*p) ) {
> +-			while( isspace(*p) ) p++;
> ++		if( isspace(static_cast<unsigned char>(*p)) ) {
> ++			while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 			if( strncasecmp(p, "min", 3) && strncasecmp(p, "maj", 3) )
> + 				break;
> + 		}
> +@@ -2687,9 +2687,9 @@ static int ABC_Key(const char *p)
> + 
> + static char *abc_skip_word(char *p)
> + {
> +-	while( isspace(*p) ) p++;
> +-	while( *p && !isspace(*p) && *p != ']') p++;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> ++	while( *p && !isspace(static_cast<unsigned char>(*p)) && *p != ']') p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	return p;
> + }
> + 
> +@@ -2798,7 +2798,7 @@ static void abc_setup_chordnames()
> + static int abc_MIDI_getnumber(const char *p)
> + {
> + 	int n;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	abc_getnumber(p, &n);
> + 	if( n < 0 )   n = 0;
> + 	if( n > 127 ) n = 127;
> +@@ -2808,7 +2808,7 @@ static int abc_MIDI_getnumber(const char *p)
> + static int abc_MIDI_getprog(const char *p)
> + {
> + 	int n;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	abc_getnumber(p, &n);
> + 	if( n < 1 )   n = 1;
> + 	if( n > 128 ) n = 128;
> +@@ -2819,32 +2819,32 @@ static int abc_MIDI_getprog(const char *p)
> + static void abc_MIDI_drone(const char *p, int *gm, int *ptch, int *vol)
> + {
> + 	int i;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	p += abc_getnumber(p, &i);
> + 	i++;	// adjust for 1..128
> + 	if( i>0 && i < 129 )
> + 		*gm = i;
> + 	else
> + 		*gm = 71;	// bassoon
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	p += abc_getnumber(p, &i);
> + 	if( i>0 && i < 127 )
> + 		ptch[0] = i;
> + 	else
> + 		ptch[0] = 45;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	p += abc_getnumber(p, &i);
> + 	if( i>0 && i < 127 )
> + 		ptch[1] = i;
> + 	else
> + 		ptch[1] = 33;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	p += abc_getnumber(p, &i);
> + 	if( i>0 && i < 127 )
> + 		vol[0] = i;
> + 	else
> + 		vol[0] = 80;
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	p += abc_getnumber(p, &i);
> + 	if( i>0 && i < 127 )
> + 		vol[1] = i;
> +@@ -2869,8 +2869,8 @@ static void abc_MIDI_channel(const char *p, ABCTRACK *tp, ABCHANDLE *h)
> + {
> + 	int i1, i2;
> + 	i1 = tp? tp->vno: 1;
> +-	for( ; *p && isspace(*p); p++ ) ;
> +-	if( isdigit(*p) ) {
> ++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++	if( isdigit(static_cast<unsigned char>(*p)) ) {
> + 		p += abc_getnumber(p, &i2);
> + 		if( i2 >= 1 && i2 <= 16 )
> + 			abc_chan_to_tracks(h, i1, i2); // we start at 1
> +@@ -2894,11 +2894,11 @@ static void abc_MIDI_program(const char *p, ABCTRACK *tp, ABCHANDLE *h)
> + {
> + 	int i1, i2;
> + 	i1 = tp? tp->vno: 1;
> +-	for( ; *p && isspace(*p); p++ ) ;
> +-	if( isdigit(*p) ) {
> ++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++	if( isdigit(static_cast<unsigned char>(*p)) ) {
> + 		p += abc_getnumber(p, &i2);
> +-		for( ; *p && isspace(*p); p++ ) ;
> +-		if( isdigit(*p) ) {
> ++		for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++		if( isdigit(static_cast<unsigned char>(*p)) ) {
> + 			i1 = i2;
> + 			abc_getnumber(p, &i2);
> + 		}
> +@@ -2919,25 +2919,25 @@ static void abc_mute_voice(ABCHANDLE *h, ABCTRACK *tp, int m)
> + static void abc_MIDI_voice(const char *p, ABCTRACK *tp, ABCHANDLE *h)
> + {
> + 	int i1, i2;
> +-	for( ; *p && isspace(*p); p++ ) ;
> ++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 	if( strncmp(p,"instrument=",11) && strncmp(p,"mute",4) ) {
> + 		tp = abc_locate_track(h, p, 0);
> +-		for( ; *p && !isspace(*p); p++ ) ;
> +-		for( ; *p && isspace(*p); p++ ) ;
> ++		for( ; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++		for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 	}
> + 	i1 = tp? tp->vno: 1;
> + 	i2 = 0;
> +-	if( !strncmp(p,"instrument=",11) && isdigit(p[11]) ) {
> ++	if( !strncmp(p,"instrument=",11) && isdigit(static_cast<unsigned char>(p[11])) ) {
> + 		p += 11;
> + 		p += abc_getnumber(p, &i2);
> +-		for( ; *p && isspace(*p); p++ ) ;
> +-		if( !strncmp(p,"bank=",5) && isdigit(p[5]) ) {
> +-			for( ; *p && !isspace(*p); p++ ) ;
> +-			for( ; *p && isspace(*p); p++ ) ;
> ++		for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++		if( !strncmp(p,"bank=",5) && isdigit(static_cast<unsigned char>(p[5])) ) {
> ++			for( ; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++			for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 		}
> + 	}
> + 	if( tp ) abc_mute_voice(h,tp,0);
> +-	if( !strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || isspace(p[4])) ) {
> ++	if( !strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || isspace(static_cast<unsigned char>(p[4]))) ) {
> + 		if( tp ) abc_mute_voice(h,tp,1);
> + 	}
> + 	abc_instr_to_tracks(h, i1, i2); // starts already at 1 (draft 4.0)
> +@@ -2949,7 +2949,7 @@ static void abc_MIDI_chordname(const char *p)
> + 	char name[20];
> + 	int i;
> + 
> +-	for(; *p && isspace(*p); p++)
> ++	for(; *p && isspace(static_cast<unsigned char>(*p)); p++)
> + 		;
> + 	i = 0;
> + 	while ((i < 19) && (*p != ' ') && (*p != '\0')) {
> +@@ -2965,8 +2965,8 @@ static void abc_MIDI_chordname(const char *p)
> + 		int notes[6];
> + 		i = 0;
> + 		memset(notes, 0, sizeof(notes));
> +-		while ((i < 6) && isspace(*p)) {
> +-			for(; *p && isspace(*p); p++)
> ++		while ((i < 6) && isspace(static_cast<unsigned char>(*p))) {
> ++			for(; *p && isspace(static_cast<unsigned char>(*p)); p++)
> + 				;
> + 			p += abc_getnumber(p, &notes[i]);
> + 			i = i + 1;
> +@@ -2981,21 +2981,21 @@ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
> + {
> + 	char *q;
> + 	int i, n, m, len;
> +-	while( isspace(*p) ) p++;
> +-	if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2;
> +-	if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> ++	if( !strncmp(p,"on",2) && (isspace(static_cast<unsigned char>(p[2])) || p[2] == '\0') ) return 2;
> ++	if( !strncmp(p,"off",3) && (isspace(static_cast<unsigned char>(p[3])) || p[3] == '\0') ) return 1;
> + 	n = 0; len = 0;
> +-	for( q = h->drum; *p && !isspace(*p); p++ ) {
> ++	for( q = h->drum; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) {
> + 		if( !strchr("dz0123456789",*p) ) break;
> + 		*q++ = *p; len++;
> +-		if( !isdigit(*p) && len < (int)sizeof(h->drum)-1 ) {
> +-			if( !isdigit(p[1]) ) { *q++ = '1'; len ++; }
> ++		if( !isdigit(static_cast<unsigned char>(*p)) && len < (int)sizeof(h->drum)-1 ) {
> ++			if( !isdigit(static_cast<unsigned char>(p[1])) ) { *q++ = '1'; len ++; }
> + 			n++; // count the silences too....
> + 		}
> + 		if (len >= (int)sizeof(h->drum)-1) {
> + 			// consume the rest of the input
> + 			// definitely enough "drum last state" stored.
> +-			while ( *p && !isspace(*p) ) p++;
> ++			while ( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
> + 			break;
> + 		}
> + 	}
> +@@ -3003,10 +3003,10 @@ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
> + 	q = h->drumins;
> + 	for( i = 0; i<n; i++ ) {
> + 		if( h->drum[i*2] == 'd' ) {
> +-			while( *p && isspace(*p) ) p++;
> +-			if( !isdigit(*p) ) {
> ++			while( *p && isspace(static_cast<unsigned char>(*p)) ) p++;
> ++			if( !isdigit(static_cast<unsigned char>(*p)) ) {
> + 				m = 0;
> +-				while( *p && !isspace(*p) ) p++;
> ++				while( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
> + 			}
> + 			else
> + 				p += abc_getnumber(p,&m);
> +@@ -3017,10 +3017,10 @@ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
> + 	q = h->drumvol;
> + 	for( i = 0; i<n; i++ ) {
> + 		if( h->drum[i*2] == 'd' ) {
> +-			while( *p && isspace(*p) ) p++;
> +-			if( !isdigit(*p) ) {
> ++			while( *p && isspace(static_cast<unsigned char>(*p)) ) p++;
> ++			if( !isdigit(static_cast<unsigned char>(*p)) ) {
> + 				m = 0;
> +-				while( *p && !isspace(*p) ) p++;
> ++				while( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
> + 			}
> + 			else
> + 				p += abc_getnumber(p,&m);
> +@@ -3036,17 +3036,17 @@ static int abc_MIDI_gchord(const char *p, ABCHANDLE *h)
> + {
> + 	char *q;
> + 	int len = 0;
> +-	while( isspace(*p) ) p++;
> +-	if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2;
> +-	if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1;
> +-	for( q = h->gchord; *p && !isspace(*p); p++ ) {
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> ++	if( !strncmp(p,"on",2) && (isspace(static_cast<unsigned char>(p[2])) || p[2] == '\0') ) return 2;
> ++	if( !strncmp(p,"off",3) && (isspace(static_cast<unsigned char>(p[3])) || p[3] == '\0') ) return 1;
> ++	for( q = h->gchord; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) {
> + 		if( !strchr("fbcz0123456789ghijGHIJ",*p) ) break;
> + 		*q++ = *p; len++;
> +-		if( !isdigit(*p) && len < (int)sizeof(h->gchord)-1 && !isdigit(p[1]) ) { *q++ = '1'; len ++; }
> ++		if( !isdigit(static_cast<unsigned char>(*p)) && len < (int)sizeof(h->gchord)-1 && !isdigit(static_cast<unsigned char>(p[1])) ) { *q++ = '1'; len ++; }
> + 		if (len >= (int)sizeof(h->gchord)-1) {
> + 			// consume the rest of the input
> + 			// definitely enough "drum last state" stored.
> +-			while ( *p && !isspace(*p) ) p++;
> ++			while ( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
> + 			break;
> + 		}
> + 	}
> +@@ -3099,7 +3099,7 @@ static void abc_metric_gchord(ABCHANDLE *h, int mlen, int mdiv)
> + 
> + static void abc_MIDI_legato(const char *p, ABCTRACK *tp)
> + {
> +-	for( ; *p && isspace(*p); p++ ) ;
> ++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 	if( !strncmp(p,"off",3) ) tp->legato = 0;
> + 	else tp->legato = 1;
> + }
> +@@ -3130,7 +3130,7 @@ static int abc_drum_steps(const char *dch)
> + 	const char *p;
> + 	int i=0;
> + 	for( p=dch; *p; p++ ) {
> +-		if( isdigit(*p) ) i += *p - '0';;
> ++		if( isdigit(static_cast<unsigned char>(*p)) ) i += *p - '0';;
> + 	}
> + 	return i;
> + }
> +@@ -3185,7 +3185,7 @@ static int abc_gchord_steps(const char *gch)
> + 	const char *p;
> + 	int i=0;
> + 	for( p=gch; *p; p++ )
> +-		if( isdigit(*p) ) i += *p - '0';
> ++		if( isdigit(static_cast<unsigned char>(*p)) ) i += *p - '0';
> + 	return i;
> + }
> + 
> +@@ -3231,7 +3231,7 @@ static void abc_add_gchord(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime)
> + 	stime = (tracktime - etime) * steps;
> + 	rtime = 0;
> + 	while( rtime < stime ) {
> +-		gnote = h->gchord[2*g];
> ++		gnote = static_cast<unsigned char>(h->gchord[2*g]);
> + 		glen  = h->gchord[2*g+1] - '0';
> + 		if( ++g == gsteps ) g = 0;
> + 		switch(gnote) {
> +@@ -3313,7 +3313,7 @@ static void abc_MIDI_beat(ABCHANDLE *h, const char *p)
> + 	h->beat[2] = 110;
> + 	h->beat[3] = 1;
> + 	for( j=0; j<4; j++ ) {
> +-		while( isspace(*p) ) p++;
> ++		while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 		if( *p ) {
> + 			p += abc_getnumber(p, &i);
> + 			if( i < 0   ) i = 0;
> +@@ -3336,7 +3336,7 @@ static void abc_MIDI_beat(ABCHANDLE *h, const char *p)
> + // %%MIDI beatstring fppmpmp
> + static void abc_MIDI_beatstring(ABCHANDLE *h, const char *p)
> + {
> +-	while( isspace(*p) ) p++;
> ++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 	if( h->beatstring ) _mm_free(h->allochandle, h->beatstring);
> + 	if( strlen(p) )
> + 		h->beatstring = DupStr(h->allochandle,p,strlen(p)+1);
> +@@ -3483,47 +3483,47 @@ static void abc_recalculate_tracktime(ABCHANDLE *h) {
> + static void abc_MIDI_command(ABCHANDLE *h, char *p, char delim) {
> + 	int t;
> + 	// interpret some of the possibilitys
> +-	if( !strncmp(p,"bassprog",8)    && isspace(p[8]) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1;
> +-	if( !strncmp(p,"bassvol",7)     && isspace(p[7]) ) h->abcbassvol = abc_MIDI_getnumber(p+7);
> +-	if( !strncmp(p,"beat",4)        && isspace(p[4]) ) abc_MIDI_beat(h, p+4);
> +-	if( !strncmp(p,"beatstring",10) && isspace(p[10]) ) abc_MIDI_beatstring(h, p+4);
> +-	if( !strncmp(p,"chordname",9)   && isspace(p[9]) ) abc_MIDI_chordname(p+9);
> +-	if( !strncmp(p,"chordprog",9)   && isspace(p[9]) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1;
> +-	if( !strncmp(p,"chordvol",8)    && isspace(p[8]) ) h->abcchordvol = abc_MIDI_getnumber(p+8);
> +-	if( !strncmp(p,"drone",5)       && isspace(p[5]) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol);
> +-	if( !strncmp(p,"droneoff",8)    && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->droneon = 0;
> +-	if( !strncmp(p,"droneon",7)     && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->droneon = 1;
> ++	if( !strncmp(p,"bassprog",8)    && isspace(static_cast<unsigned char>(p[8])) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1;
> ++	if( !strncmp(p,"bassvol",7)     && isspace(static_cast<unsigned char>(p[7])) ) h->abcbassvol = abc_MIDI_getnumber(p+7);
> ++	if( !strncmp(p,"beat",4)        && isspace(static_cast<unsigned char>(p[4])) ) abc_MIDI_beat(h, p+4);
> ++	if( !strncmp(p,"beatstring",10) && isspace(static_cast<unsigned char>(p[10])) ) abc_MIDI_beatstring(h, p+4);
> ++	if( !strncmp(p,"chordname",9)   && isspace(static_cast<unsigned char>(p[9])) ) abc_MIDI_chordname(p+9);
> ++	if( !strncmp(p,"chordprog",9)   && isspace(static_cast<unsigned char>(p[9])) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1;
> ++	if( !strncmp(p,"chordvol",8)    && isspace(static_cast<unsigned char>(p[8])) ) h->abcchordvol = abc_MIDI_getnumber(p+8);
> ++	if( !strncmp(p,"drone",5)       && isspace(static_cast<unsigned char>(p[5])) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol);
> ++	if( !strncmp(p,"droneoff",8)    && (p[8]=='\0' || p[8]==delim || isspace(static_cast<unsigned char>(p[8]))) ) h->droneon = 0;
> ++	if( !strncmp(p,"droneon",7)     && (p[7]=='\0' || p[7]==delim || isspace(static_cast<unsigned char>(p[7]))) ) h->droneon = 1;
> + 	t = h->drumon;
> +-	if( !strncmp(p,"drum",4)        && isspace(p[4]) ) {
> ++	if( !strncmp(p,"drum",4)        && isspace(static_cast<unsigned char>(p[4])) ) {
> + 		h->drumon = abc_MIDI_drum(p+4, h);
> + 		if( h->drumon ) --h->drumon;
> + 		else h->drumon = t;
> + 	}
> +-	if( !strncmp(p,"drumoff",7)     && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->drumon = 0;
> +-	if( !strncmp(p,"drumon",6)      && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) h->drumon = 1;
> ++	if( !strncmp(p,"drumoff",7)     && (p[7]=='\0' || p[7]==delim || isspace(static_cast<unsigned char>(p[7]))) ) h->drumon = 0;
> ++	if( !strncmp(p,"drumon",6)      && (p[6]=='\0' || p[6]==delim || isspace(static_cast<unsigned char>(p[6]))) ) h->drumon = 1;
> + 	if( t != h->drumon ) {
> + 		if( h->drumon && !h->tpr ) h->tpr = h->track;
> + 		if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time!
> + 		if( h->tpr && !h->drumon ) h->tpr = NULL;
> + 	}
> + 	t = h->gchordon;
> +-	if( !strncmp(p,"gchord",6)      && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) {
> ++	if( !strncmp(p,"gchord",6)      && (p[6]=='\0' || p[6]==delim || isspace(static_cast<unsigned char>(p[6]))) ) {
> + 		h->gchordon = abc_MIDI_gchord(p+6, h);
> + 		if( h->gchordon ) --h->gchordon;
> + 		else h->gchordon = t;
> + 	}
> +-	if( !strncmp(p,"gchordoff",9)   && (p[9]=='\0' || p[9]==delim || isspace(p[9])) ) h->gchordon = 0;
> +-	if( !strncmp(p,"gchordon",8)    && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->gchordon = 1;
> ++	if( !strncmp(p,"gchordoff",9)   && (p[9]=='\0' || p[9]==delim || isspace(static_cast<unsigned char>(p[9]))) ) h->gchordon = 0;
> ++	if( !strncmp(p,"gchordon",8)    && (p[8]=='\0' || p[8]==delim || isspace(static_cast<unsigned char>(p[8]))) ) h->gchordon = 1;
> + 	if( t != h->gchordon ) {
> + 		if( h->tpc ) abc_add_gchord_syncs(h, h->tpc, h->tracktime);
> + 	}
> +-	if( !strncmp(p,"channel",7)     && isspace(p[7]) )
> ++	if( !strncmp(p,"channel",7)     && isspace(static_cast<unsigned char>(p[7])) )
> + 		abc_MIDI_channel(p+8, h->tp = abc_check_track(h, h->tp), h);
> +-	if( !strncmp(p,"program",7)     && isspace(p[7]) )
> ++	if( !strncmp(p,"program",7)     && isspace(static_cast<unsigned char>(p[7])) )
> + 		abc_MIDI_program(p+8, h->tp = abc_check_track(h, h->tp), h);
> +-	if( !strncmp(p,"voice",5)       && isspace(p[5]) )
> ++	if( !strncmp(p,"voice",5)       && isspace(static_cast<unsigned char>(p[5])) )
> + 		abc_MIDI_voice(p+6, h->tp = abc_check_track(h, h->tp), h);
> +-	if( !strncmp(p,"legato",6)      && (p[6]=='\0' || p[6]==delim || isspace(p[6])) )
> ++	if( !strncmp(p,"legato",6)      && (p[6]=='\0' || p[6]==delim || isspace(static_cast<unsigned char>(p[6]))) )
> + 		abc_MIDI_legato(p+6, h->tp = abc_check_track(h, h->tp));
> + }
> + 
> +@@ -3548,13 +3548,13 @@ static char *abc_continuated(ABCHANDLE *h, MMFILE *mmf, char *p) {
> + 				abc_message("line not properly continued\n%s", p1);
> + 				return p1;
> + 			}
> +-			while( *pm && isspace(*pm) ) ++pm;
> ++			while( *pm && isspace(static_cast<unsigned char>(*pm)) ) ++pm;
> + 			if( !strncmp(pm,"%%",2) ) {
> +-				for( p2 = pm+2; *p2 && isspace(*p2); p2++ ) ;
> +-				if( !strncmp(p2,"MIDI",4) && (p2[4]=='=' || isspace(p2[4])) ) {
> +-					for( p2+=5; *p2 && isspace(*p2); p2++ ) ;
> ++				for( p2 = pm+2; *p2 && isspace(static_cast<unsigned char>(*p2)); p2++ ) ;
> ++				if( !strncmp(p2,"MIDI",4) && (p2[4]=='=' || isspace(static_cast<unsigned char>(p2[4]))) ) {
> ++					for( p2+=5; *p2 && isspace(static_cast<unsigned char>(*p2)); p2++ ) ;
> + 					if( *p2 == '=' )
> +-						for( p2+=1; *p2 && isspace(*p2); p2++ ) ;
> ++						for( p2+=1; *p2 && isspace(static_cast<unsigned char>(*p2)); p2++ ) ;
> + 					abc_MIDI_command(h,p2,'%');
> + 				}
> + 				continued = 1;
> +@@ -3685,7 +3685,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 		abcxcount = 0;
> + 		mmfseek(mmfile,0,SEEK_SET);
> + 		while ((line=abc_gets(h, mmfile)) != NULL) {
> +-			for( p=line; isspace(*p); p++ ) ;
> ++			for( p=line; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 			if( !strncmp(p,"X:",2) ) abcxcount++;
> + 		}
> + 		if( abcxcount == 0 )
> +@@ -3699,7 +3699,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 		mmsp--;
> + 		while ((line=abc_gets(h, mmstack[mmsp])) != NULL) {
> + 			char blankline[3] = "% ";
> +-			for( p=line; isspace(*p); p++ ) ;
> ++			for( p=line; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 			switch(abcstate) {
> + 				case INSKIPFORX:
> + 					if( !strncmp(p,"X:",2) ) {
> +@@ -3711,7 +3711,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 					if( !strncmp(p,"X:",2) ) {
> + 						abcstate = INHEAD;
> + 						memset(m_szNames[0], 0, 32);
> +-						for( p+=2; isspace(*p); p++ ) ;
> ++						for( p+=2; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 						abcxnumber = atoi(p);
> + 						abchornpipe = 0;
> + 						h->droneon = 0;
> +@@ -3792,8 +3792,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 						break;
> + 					}
> + 					if( !strncmp(p,"R:",2) ) {
> +-						for( p+=2; isspace(*p); p++ ) ;
> +-						if( !strncmp(p,"hornpipe",8) && (isspace(p[8]) || p[8]=='\0') ) abchornpipe = 1;
> ++						for( p+=2; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++						if( !strncmp(p,"hornpipe",8) && (isspace(static_cast<unsigned char>(p[8])) || p[8]=='\0') ) abchornpipe = 1;
> + 						else abchornpipe = 0;
> + 						break;
> + 					}
> +@@ -3980,8 +3980,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 				p[1]= '%';
> + 			}
> + 			if( !strncmp(p,"%%",2) ) {
> +-				for( p+=2; *p && isspace(*p); p++ ) ;
> +-				if( !strncmp(p,"abc-include",11) && isspace(p[11]) ) {
> ++				for( p+=2; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++				if( !strncmp(p,"abc-include",11) && isspace(static_cast<unsigned char>(p[11])) ) {
> + 					for( t=12; isspace(p[t]); t++ ) ;
> + 					if( p[t] ) {
> + 						mmsp++;
> +@@ -3998,10 +3998,10 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 					}
> + 					else abc_message("failure: abc-include missing file name, %s", p);
> + 				}
> +-				if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) && abcstate != INSKIPFORX ) {
> +-					for( p+=5; *p && isspace(*p); p++ ) ;
> ++				if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(static_cast<unsigned char>(p[4]))) && abcstate != INSKIPFORX ) {
> ++					for( p+=5; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 					if( *p == '=' )
> +-						for( p+=1; *p && isspace(*p); p++ ) ;
> ++						for( p+=1; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 					abc_MIDI_command(h,p,'%');
> + 					if( h->tp ) abcnolegato = !h->tp->legato;
> + 					if( !abcnolegato ) abcnoslurs = 0;
> +@@ -4034,7 +4034,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 							partpat[global_part - 'A'][1] = t;
> + 						// give every new coming abcevent the desired part indication
> + 						while( p[2]==' ' || p[2]=='.' ) p++;	// skip blancs and dots
> +-						if( isupper(p[2]) )
> ++						if( isupper(static_cast<unsigned char>(p[2])) )
> + 							global_part = p[2];
> + 						else
> + 							global_part = ' ';
> +@@ -4073,7 +4073,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 					ch0 = ' ';
> + 					pp = 0;
> + 					while (*p && (ch = *p++) != '\0') {
> +-						if( !pp && isalpha(ch) && *p != ':' ) { // maybe a macro
> ++						if( !pp && isalpha(static_cast<unsigned char>(ch)) && *p != ':' ) { // maybe a macro
> + 							for( mp=h->umacro; mp; mp=mp->next ) {
> + 								if( ch == mp->name[0] ) {
> + 									pp = p;
> +@@ -4131,8 +4131,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 										else
> + 											partpat[global_part - 'A'][1] = t;
> + 										// give every new coming abcevent the desired part indication
> +-										while( isspace(p[2]) || p[2]=='.' ) p++;	// skip blancs and dots
> +-										if( isupper(p[2]) )
> ++										while( isspace(static_cast<unsigned char>(p[2])) || p[2]=='.' ) p++;	// skip blancs and dots
> ++										if( isupper(static_cast<unsigned char>(p[2])) )
> + 											global_part = p[2];
> + 										else
> + 											global_part = ' ';
> +@@ -4152,11 +4152,11 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 									break;
> + 								}
> + 								if( !strncmp(p,"I:",2) ) { // interpret some of the possibilitys
> +-									for( p += 2; isspace(*p); p++ ) ;
> +-									if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) ) { // interpret some of the possibilitys
> +-										for( p += 4; isspace(*p); p++ ) ;
> ++									for( p += 2; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> ++									if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(static_cast<unsigned char>(p[4]))) ) { // interpret some of the possibilitys
> ++										for( p += 4; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 										if( *p == '=' )
> +-											for( p += 1; isspace(*p); p++ ) ;
> ++											for( p += 1; isspace(static_cast<unsigned char>(*p)); p++ ) ;
> + 										abc_MIDI_command(h, p, ']');
> + 										if( h->tp ) abcnolegato = !h->tp->legato;
> + 										if( !abcnolegato ) abcnoslurs = 0;
> +@@ -4235,7 +4235,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 									notelen *= cnotelen;
> + 									notediv *= cnotediv;
> + 									tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
> +-									while( isspace(*p) ) p++;	// allow spacing in broken rithm notation
> ++									while( isspace(static_cast<unsigned char>(*p)) ) p++;	// allow spacing in broken rithm notation
> + 									p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
> + 									thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
> + 									if( abcfermata ) {
> +@@ -4278,7 +4278,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 									if( abceffoper != 255 ) abceffect = none;
> + 									break;
> + 								}
> +-								if( isdigit(*p) ) {	// different endings in repeats [i,j,n-r,s,...
> ++								if( isdigit(static_cast<unsigned char>(*p)) ) {	// different endings in repeats [i,j,n-r,s,...
> + 									h->tp = abc_check_track(h, h->tp);
> + 									abc_add_partbreak(h, h->tp, h->tracktime);
> + 									p += abc_getnumber(p, &notelen);
> +@@ -4304,7 +4304,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 								break;
> + 							case '(':	// slurs follow or some tuplet (duplet, triplet etc.)
> + 								abcto = 0;
> +-								if( isdigit(*p) ) {
> ++								if( isdigit(static_cast<unsigned char>(*p)) ) {
> + 									p += abc_getnumber(p,&tupletp);
> + 									tupletr = tupletp;	// ABC draft 2.0 (4.13): if r is not given it defaults to p
> + 									switch( tupletp ) {	// ABC draft 2.0 (4.13): q defaults depending on p and time signature
> +@@ -4323,10 +4323,10 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 									}
> + 									if( *p==':' ) {
> + 										p++;
> +-										if( isdigit(*p) ) p += abc_getnumber(p,&tupletq);
> ++										if( isdigit(static_cast<unsigned char>(*p)) ) p += abc_getnumber(p,&tupletq);
> + 										if( *p==':' ) {
> + 											p++;
> +-											if( isdigit(*p) ) p += abc_getnumber(p,&tupletr);
> ++											if( isdigit(static_cast<unsigned char>(*p)) ) p += abc_getnumber(p,&tupletr);
> + 										}
> + 									}
> + 								}
> +@@ -4375,7 +4375,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 								sprintf(barsig, "%s%s", sig[abckey], sig[abckey]);	// reset the key signature
> + 								bartime = h->tracktime;
> + 								if( h->tp && h->tp->vpos ) h->tp = abc_locate_track(h, h->tp->v, 0); // reset from voice overlay
> +-								if( isdigit(*p) ) {	// different endings in repeats |i,j,n-r,s,...
> ++								if( isdigit(static_cast<unsigned char>(*p)) ) {	// different endings in repeats |i,j,n-r,s,...
> + 									h->tp = abc_check_track(h, h->tp);
> + 									abc_add_partbreak(h, h->tp, h->tracktime);
> + 									p += abc_getnumber(p, &notelen);
> +@@ -4426,7 +4426,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 								}
> + 								break;
> + 							case '"':	// chord notation
> +-								if( !strchr("_^<>@", *p) && !isdigit(*p) ) { // if it's not a annotation string
> ++								if( !strchr("_^<>@", *p) && !isdigit(static_cast<unsigned char>(*p)) ) { // if it's not a annotation string
> + 									h->tp = abc_check_track(h, h->tp);
> + 									if( !h->tpc ) h->tpc = abc_locate_track(h, h->tp->v, 0);
> +  									if( h->tp == h->tpc ) abc_add_chord(p, h, h->tpc, h->tracktime); // only do chords for one voice
> +@@ -4443,8 +4443,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 										abcto = -1;
> + 									}
> + 									else
> +-										if( !isspace(*p) ) abcto = 0;
> +-									if( !strncasecmp(p,"to",2) && (isspace(p[2]) || p[2] == '"') ) abcto = 1;
> ++										if( !isspace(static_cast<unsigned char>(*p)) ) abcto = 0;
> ++									if( !strncasecmp(p,"to",2) && (isspace(static_cast<unsigned char>(p[2])) || p[2] == '"') ) abcto = 1;
> + 								}
> + 								if( !ch ) abcstate = INSKIPFORQUOTE;
> + 								break;
> +@@ -4665,7 +4665,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 										h->tp->tienote = h->tp->tail;
> + 									}
> + 									tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
> +-									while( isspace(*p) ) p++;	// allow spacing in broken rithm notation
> ++									while( isspace(static_cast<unsigned char>(*p)) ) p++;	// allow spacing in broken rithm notation
> + 									p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
> + 									thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
> + 									if( abcfermata ) {
> +@@ -4699,7 +4699,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 									abc_track_clear_tiednote(h);
> + 									p += abc_notelen(p, &notelen, &notediv);
> + 									tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
> +-									while( isspace(*p) ) p++;	// allow spacing in broken rithm notation
> ++									while( isspace(static_cast<unsigned char>(*p)) ) p++;	// allow spacing in broken rithm notation
> + 									p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
> + 									thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
> + 									if( abcfermata ) {
> +@@ -4752,7 +4752,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
> + 									abcarpeggio = 0;
> + 									break;
> + 								}
> +-								if( isalpha(ch) && *p==':' ) {
> ++								if( isalpha(static_cast<unsigned char>(ch)) && *p==':' ) {
> + 									// some unprocessed field line?
> + 									while( *p ) p++;	// skip it
> + 									break;
> +diff --git a/src/load_mid.cpp b/src/load_mid.cpp
> +index fe02f5e4..749b5d0c 100644
> +--- a/src/load_mid.cpp
> ++++ b/src/load_mid.cpp
> +@@ -1198,7 +1198,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
> + 	if (h->miditracks == 0) goto ErrorCleanup;
> + 
> + 	p = (BYTE *)getenv(ENV_MMMID_SPEED);
> +-	if( p && isdigit(*p) && p[0] != '0' && p[1] == '\0' ) {
> ++	if( p && isdigit(static_cast<unsigned char>(*p)) && p[0] != '0' && p[1] == '\0' ) {
> + 		// transform speed
> + 		t = *p - '0';
> + 		h->speed *= t;
> +diff --git a/src/load_pat.cpp b/src/load_pat.cpp
> +index fe787311..dfa640e5 100644
> +--- a/src/load_pat.cpp
> ++++ b/src/load_pat.cpp
> +@@ -392,31 +392,31 @@ void pat_init_patnames(void)
> + 			_mm_fgets(mmcfg, line, PATH_MAX);
> + 			while( !_mm_feof(mmcfg) ) {
> + 			p = line;
> +-			while ( isspace(*p) ) p ++;
> +-			if( isdigit(p[0]) ) {
> ++			while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
> ++			if( isdigit(static_cast<unsigned char>(p[0])) ) {
> + 				// get pat number
> + 				i = atoi(p);
> +-				while ( isdigit(*p) ) p ++;
> +-				while ( isspace(*p) ) p ++;
> ++				while ( isdigit(static_cast<unsigned char>(*p)) ) p ++;
> ++				while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
> + 				// get pat file name
> + 				if( *p && i < MAXSMP && i >= 0 && *p != '#' ) {
> + 					q = isdrumset ? midipat[pat_gm_drumnr(i)-1] : midipat[i];
> + 					pfnlen = 0;
> +-					while( *p && !isspace(*p) && *p != '#' && pfnlen < 128 ) {
> ++					while( *p && !isspace(static_cast<unsigned char>(*p)) && *p != '#' && pfnlen < 128 ) {
> + 						pfnlen ++;
> + 						*q++ = *p++;
> + 					}
> +-					if( isblank(*p) && *(p+1) != '#' && pfnlen < 128 ) {
> ++					if( isblank(static_cast<unsigned char>(*p)) && *(p+1) != '#' && pfnlen < 128 ) {
> + 						*q++ = ':'; pfnlen ++;
> +-						while( isspace(*p) ) {
> +-							while( isspace(*p) ) p++;
> ++						while( isspace(static_cast<unsigned char>(*p)) ) {
> ++							while( isspace(static_cast<unsigned char>(*p)) ) p++;
> + 							if ( *p == '#' ) { // comment
> + 
> +-							} else while( *p && !isspace(*p) && pfnlen < 128 ) {
> ++							} else while( *p && !isspace(static_cast<unsigned char>(*p)) && pfnlen < 128 ) {
> + 								pfnlen ++;
> + 								*q++ = *p++;
> + 							}
> +-							if( isspace(*p) ) { *q++ = ' '; pfnlen++; }
> ++							if( isspace(static_cast<unsigned char>(*p)) ) { *q++ = ' '; pfnlen++; }
> + 						}
> + 					}
> + 					*q++ = '\0';
> +@@ -429,11 +429,11 @@ void pat_init_patnames(void)
> + 			}
> + 			else if( !strncmp(p,"dir",3) )  {
> + 				p += 3;
> +-				while ( isspace(*p) ) p ++;
> ++				while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
> + 				q = p + strlen(p);
> + 				if(q > p) {
> + 					--q;
> +-					while ( q > p && isspace(*q) ) *(q--) = 0;
> ++					while ( q > p && isspace(static_cast<unsigned char>(*q)) ) *(q--) = 0;
> + 					strncpy(pathforpat, p, PATH_MAX - 1);
> + 					pathforpat[PATH_MAX - 1] = 0;
> + 				}
> +@@ -441,9 +441,9 @@ void pat_init_patnames(void)
> + 			else if( !strncmp(p,"source",6) && nsources < 5 ) {
> + 				q = cfgsources[nsources];
> + 				p += 6;
> +-				while ( isspace(*p) ) p ++;
> ++				while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
> + 				pfnlen = 0;
> +-				while ( *p && *p != '#' && !isspace(*p) && pfnlen < 128 ) {
> ++				while ( *p && *p != '#' && !isspace(static_cast<unsigned char>(*p)) && pfnlen < 128 ) {
> + 					pfnlen ++;
> + 					*q++ = *p++;
> + 				}
> +@@ -857,7 +857,7 @@ static void PAT_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], PATHANDLE *h,
> + 					i = tt2 - 16 * ((h->samples - 1 - ch) & 3);
> + 					if( tt1 < i ) {
> + 						t = t % 64;
> +-						if( isalpha(tune[t]) ) {
> ++						if( isalpha(static_cast<unsigned char>(tune[t])) ) {
> + 							n   = pat_modnote(pat_note(tune[t]));
> + 							ins = ch + 1;
> + 							vol = 40;
> -- 
> 2.37.2
> 
> 
> _______________________________________________
> buildroot mailing list
> buildroot@buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
>
Peter Korsgaard Oct. 13, 2023, 3:02 p.m. UTC | #2
>>>>> "Yann" == Yann E MORIN <yann.morin.1998@free.fr> writes:

 > Gleb, All,
 > Sorry for the delay, now I've handled that patch...

 > On 2023-01-09 22:00 +0000, Gleb Mazovetskiy spake thusly:
 >> libmodplug calls `cctype` functions, such as `isspace`,
 >> with negative values. This is undefined behaviour.
 >> 
 >> While glibc allows it, it crashes on uClibc compiled
 >> without `UCLIBC_HAS_CTYPE_SIGNED`.
 >> 
 >> Adds a patch that resolves the issue.

 > We discussed it during the hackathon this WE, and we were a bit ,eh
 > about that patch, because it is a bit big, and upstream has not
 > responded to it.

 > However, upstream does indeed look pretty dead with no activity in the
 > past two years and only the occasional commit before that, so there is
 > very low risk at integrating this patch in Buildroot, as it should not
 > cause much maintenance issue. On the off chance upstream ever release
 > something new, we can assess the situation then.

 >> Also sent upstream. However, the library author has not merged
 >> any pull request for about a year.
 >> https://github.com/Konstanty/libmodplug/pull/92
 >> 
 >> Signed-off-by: Gleb Mazovetskiy <glex.spb@gmail.com>

 >     $ make check-package
 >     package/libmodplug/0001-fix-cctype-ub.patch:0: missing
 > Signed-off-by in the header
 > (http://nightly.buildroot.org/#_format_and_licensing_of_the_package_patches)
 >     package/libmodplug/0001-fix-cctype-ub.patch:0: missing Upstream in
 > the header
 > (http://nightly.buildroot.org/#_additional_patch_documentation)

 > The latter is newer than your patch, so that's not your fault; I fixed
 > it when applying.

 > For the former, since your SoB-ed your Buildoot contribution, I
 > copy-pasted it to the bundled patch too.

 > Applied to master with that fixed, thanks.

 > Eh, btw: I'm surprised people are still doing MOD nowadays! :-)

Committed to 2023.02.x and 2023.08.x, thanks.
diff mbox series

Patch

diff --git a/package/libmodplug/0001-fix-cctype-ub.patch b/package/libmodplug/0001-fix-cctype-ub.patch
new file mode 100644
index 0000000000..15e7d364e5
--- /dev/null
+++ b/package/libmodplug/0001-fix-cctype-ub.patch
@@ -0,0 +1,954 @@ 
+From dc6d5994b4912cb00d0d183b400edfd656d6530c Mon Sep 17 00:00:00 2001
+From: Gleb Mazovetskiy <glex.spb@gmail.com>
+Date: Wed, 21 Dec 2022 11:44:27 +0000
+Subject: [PATCH] Fix UB when calling cctype functions
+
+Calling cctype functions, such as isspace, with negative values
+is undefined behaviour.
+
+While glibc allows it, it crashes on uClibc compiled without
+`UCLIBC_HAS_CTYPE_SIGNED`.
+
+Fixes the undefined behaviour by casting all arguments to
+cctype functions to `unsigned char`.
+---
+ src/load_abc.cpp | 284 +++++++++++++++++++++++------------------------
+ src/load_mid.cpp |   2 +-
+ src/load_pat.cpp |  30 ++---
+ 3 files changed, 158 insertions(+), 158 deletions(-)
+
+diff --git a/src/load_abc.cpp b/src/load_abc.cpp
+index b45f972f..8444bd87 100644
+--- a/src/load_abc.cpp
++++ b/src/load_abc.cpp
+@@ -260,13 +260,13 @@ static uint32_t abc_pattracktime(ABCHANDLE *h, uint32_t tracktime);
+ static int abc_patno(ABCHANDLE *h, uint32_t tracktime);
+ 
+ 
+-static int abc_isvalidchar(char c) {
++static int abc_isvalidchar(unsigned char c) {
+ 	return(isalpha(c) || isdigit(c) || isspace(c) || c == '%' || c == ':');
+ }
+ #if 0
+ static const char *abc_skipspace(const char *p)
+ {
+-	while (*p && isspace(*p))
++	while (*p && isspace(static_cast<unsigned char>(*p)))
+ 		p++;
+ 	return p;
+ }
+@@ -275,7 +275,7 @@ static const char *abc_skipspace(const char *p)
+ static void abc_extractkeyvalue(char *key, size_t key_max,
+ 								char *value, size_t value_max, const char *src)
+ {
+-	while (*src && isspace(*src))
++	while (*src && isspace(static_cast<unsigned char>(*src)))
+ 		src++;
+ 
+ 	size_t key_size;
+@@ -286,17 +286,17 @@ static void abc_extractkeyvalue(char *key, size_t key_max,
+ 		}
+ 		key[key_size++] = *src++;
+ 	}
+-	while (key_size > 0 && isspace(key[key_size - 1]))
++	while (key_size > 0 && isspace(static_cast<unsigned char>(key[key_size - 1])))
+ 		key_size--;
+ 	key[key_size] = '\0';
+ 
+-	while (*src && isspace(*src))
++	while (*src && isspace(static_cast<unsigned char>(*src)))
+ 		src++;
+ 
+ 	size_t value_size;
+ 	for (value_size = 0; value_size < value_max - 1 && *src;)
+ 		value[value_size++] = *src++;
+-	while (value_size > 0 && isspace(value[value_size - 1]))
++	while (value_size > 0 && isspace(static_cast<unsigned char>(value[value_size - 1])))
+ 		value_size--;
+ 	value[value_size] = '\0';
+ 
+@@ -359,7 +359,7 @@ static void abc_dumptracks(ABCHANDLE *h, const char *p)
+ 					nn[0] = "CCCDDEFFGGAABccddeffggaabb"[e->par[chordnote]];
+ 					nn[1] = "b # #  # # #  # #  # # # #"[e->par[chordnote]];
+ 					nn[2] = '\0';
+-					if( isspace(nn[1]) ) nn[1] = '\0';
++					if( isspace(static_cast<unsigned char>(nn[1])) ) nn[1] = '\0';
+ 					printf("CMD %c: gchord %s%s",
+ 					       (char)(e->cmd), nn, chordname[e->par[chordnum]]);
+ 					if( e->par[chordbase] != e->par[chordnote] ) {
+@@ -557,7 +557,7 @@ static void abc_new_umacro(ABCHANDLE *h, const char *m)
+ 	ABCMACRO *retval, *mp;
+ 	char key[256], value[256];
+ 	abc_extractkeyvalue(key, sizeof(key), value, sizeof(value), m);
+-	if( strlen(key) > 1 || strchr("~HIJKLMNOPQRSTUVWXY",toupper(key[0])) == 0 ) return;
++	if( strlen(key) > 1 || strchr("~HIJKLMNOPQRSTUVWXY",toupper(static_cast<unsigned char>(key[0]))) == 0 ) return;
+ 	while( char *q = strchr(key, '!') )
+ 		*q = '+'; // translate oldstyle to newstyle
+ 	if( !strcmp(key,"+nil+") ) { // delete a macro
+@@ -823,7 +823,7 @@ static ABCTRACK *abc_locate_track(ABCHANDLE *h, const char *voice, int pos)
+ 	char vc[21];
+ 	int i, trans=0, voiceno=0, instrno = 1, channo = 0;
+ 	for( ; *voice == ' '; voice++ ) ;	// skip leading spaces
+-	for( i=0; i+1 < (int) sizeof(vc) && *voice && *voice != ']' && *voice != '%' && !isspace(*voice); voice++ )	// can work with inline voice instructions
++	for( i=0; i+1 < (int) sizeof(vc) && *voice && *voice != ']' && *voice != '%' && !isspace(static_cast<unsigned char>(*voice)); voice++ )	// can work with inline voice instructions
+ 		vc[i++] = *voice;
+ 	vc[i] = '\0';
+ 	prev = NULL;
+@@ -1250,32 +1250,32 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim
+ 	switch(ch) {
+ 		case '^':
+ 			if( p[0] == '^' ) {
+-				n = p[1];
++				n = static_cast<unsigned char>(p[1]);
+ 				i = 2;
+ 				ch = 'x';
+ 			}
+ 			else {
+-				n = p[0];
++				n = static_cast<unsigned char>(p[0]);
+ 				i = 1;
+ 			}
+ 			break;
+ 		case '_':
+ 			if( p[0] == '_' ) {
+-				n = p[1];
++				n = static_cast<unsigned char>(p[1]);
+ 				i = 2;
+ 				ch = 'b';
+ 			}
+ 			else {
+-				n = p[0];
++				n = static_cast<unsigned char>(p[0]);
+ 				i = 1;
+ 			}
+ 			break;
+ 		case '=':
+-			n = p[0];
++			n = static_cast<unsigned char>(p[0]);
+ 			i = 1;
+ 			break;
+ 		default:
+-			n = ch;
++			n = static_cast<unsigned char>(ch);
+ 			i = 0;
+ 			break;
+ 	}
+@@ -1332,7 +1332,7 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim
+ 	}
+ 	else
+ 		d[note] = 0; // someone has doen ^X3 or something like it...
+-	while( p[i] && strchr(",'",p[i]) ) {
++	while( p[i] && strchr(",'",static_cast<unsigned char>(p[i])) ) {
+ 		if( p[i]==',' ) oct--;
+ 		else oct++;
+ 		i++;
+@@ -1381,7 +1381,7 @@ static int abc_add_noteon(ABCHANDLE *h, int ch, const char *p, uint32_t tracktim
+ 			}
+ 		}
+ 		tp->tienote->tiednote = 1; // mark him for the pattern writers
+-		for( j=i; isdigit(p[j]) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too
++		for( j=i; isdigit(static_cast<unsigned char>(p[j])) || p[j]=='/'; j++ ) ; // look ahead to see if this one is tied too
+ 		if( p[j] != '-' ) // is this note tied too?
+ 			tp->tienote = NULL; // if not the tie ends here...
+ 		return i;
+@@ -1603,7 +1603,7 @@ static int abc_getnumber(const char *p, int *number)
+ 	int i,h;
+ 	i = 0;
+ 	h = 0;
+-	while( isdigit(p[i]) ) {
++	while( isdigit(static_cast<unsigned char>(p[i])) ) {
+ 		if (i < 9)
+ 			h = 10 * h + p[i] - '0';
+ 		i++;
+@@ -1619,7 +1619,7 @@ static int abc_getexpr(const char *p, int *number)
+ {
+ 	int i, term, total;
+ 	i = 0;
+-	while( isspace(p[i]) )
++	while( isspace(static_cast<unsigned char>(p[i])) )
+ 		i++;
+ 	if( p[i] == '(' ) {
+ 		i += abc_getexpr(p+i+1, number);
+@@ -1628,12 +1628,12 @@ static int abc_getexpr(const char *p, int *number)
+ 		return i;
+ 		}
+ 	i += abc_getnumber(p+i, &total);
+-	while( isspace(p[i]) )
++	while( isspace(static_cast<unsigned char>(p[i])) )
+ 		i++;
+ 	while( p[i] == '+' ) {
+ 		i += 1 + abc_getexpr(p+i+1, &term);
+ 		total += term;
+-		while( isspace(p[i]) )
++		while( isspace(static_cast<unsigned char>(p[i])) )
+ 			i++;
+ 	}
+ 	*number = total;
+@@ -1649,7 +1649,7 @@ static int abc_notelen(const char *p, int *len, int *div)
+ 		h *= 2;
+ 		i++;
+ 	}
+-	if( isdigit(p[i]) ) {
++	if( isdigit(static_cast<unsigned char>(p[i])) ) {
+ 		h /= 2;
+ 		i += abc_getnumber(p+i,&k);
+ 	}
+@@ -1738,7 +1738,7 @@ static int abc_extract_tempo(const char *p, int invoice)
+ 				case '=':
+ 					break;
+ 				default:
+-					if( isdigit(*q) ) {
++					if( isdigit(static_cast<unsigned char>(*q)) ) {
+ 						if( state ) {
+ 							q+=abc_getnumber(q,&nd1)-1;
+ 							state = 0;
+@@ -1812,10 +1812,10 @@ static void	abc_set_parts(char **d, char *p)
+ 	j=0;
+ 	k=0;
+ 	for( i=0; p[i] && p[i] != '%'; i++ ) {
+-		if( isupper(p[i]) ) {
++		if( isupper(static_cast<unsigned char>(p[i])) ) {
+ 			j++;
+ 		}
+-		if( isdigit(p[i]) ) {
++		if( isdigit(static_cast<unsigned char>(p[i])) ) {
+ 			n=abc_getnumber(p+i, &k);
+ 			if( k == 0 )
+ 				k = 1;
+@@ -1833,7 +1833,7 @@ static void	abc_set_parts(char **d, char *p)
+ 	// now copy bytes from p to *d, taking parens and digits in account
+ 	j = 0;
+ 	for( i=0; p[i] && p[i] != '%' && j < size && i < (int)size; i++ ) {
+-		if( isdigit(p[i]) || isupper(p[i]) || p[i] == '(' || p[i] == ')' ) {
++		if( isdigit(static_cast<unsigned char>(p[i])) || isupper(static_cast<unsigned char>(p[i])) || p[i] == '(' || p[i] == ')' ) {
+ 			if( p[i] == ')' ) {
+ 				for( n=j; n > 0 && q[n-1] != '('; n-- )	;	// find open paren in q
+ 				// q[n+1] to q[j] contains the substring that must be repeated
+@@ -1856,7 +1856,7 @@ static void	abc_set_parts(char **d, char *p)
+ 				}
+ 				continue;
+ 			}
+-			if( isdigit(p[i]) ) {
++			if( isdigit(static_cast<unsigned char>(p[i])) ) {
+ 				n = abc_getnumber(p+i,&k);
+ 				i += n - 1;
+ 				// if nothing is ready to 'repeat', skip it.
+@@ -2243,7 +2243,7 @@ static void abc_preprocess(ABCHANDLE *h, ABCMACRO *m)
+ 			char *p = s;
+ 			for( j=0; j<l; j++ ) {
+ 				a = m->subst[j];
+-				if( a > 'g' && islower(a) ) {
++				if( a > 'g' && islower(static_cast<unsigned char>(a)) ) {
+ 					b = a - 'n';
+ 					a = "CDEFGABCDEFGABcdefgabcdefgabcdefgab"[i+b+7];
+ 					*p++ = a;
+@@ -2339,11 +2339,11 @@ BOOL CSoundFile::TestABC(const BYTE *lpStream, DWORD dwMemLength)
+ 		}
+ 		if(id[0]=='K'
+ 			&& id[1]==':'
+-			&& (isalpha(id[2]) || isspace(id[2])) ) return 1;
++			&& (isalpha(static_cast<unsigned char>(id[2])) || isspace(static_cast<unsigned char>(id[2]))) ) return 1;
+ 		// disable binary error if have any "tag"
+ 		if((id[0]>='A' && id[0]<='Z')
+ 			&& id[1]==':'
+-			&& (isalpha(id[2]) || isspace(id[2])) ) hasText = 1;
++			&& (isalpha(static_cast<unsigned char>(id[2])) || isspace(static_cast<unsigned char>(id[2]))) ) hasText = 1;
+ 	}
+ 	return 0;
+ }
+@@ -2367,7 +2367,7 @@ static ABCHANDLE *ABC_Init(void)
+ 	retval->barticks    = 0;
+ 	p = getenv(ABC_ENV_NORANDOMPICK);
+ 	if( p ) {
+-		if( isdigit(*p) )
++		if( isdigit(static_cast<unsigned char>(*p)) )
+ 			retval->pickrandom = atoi(p);
+ 		if( *p == '-' ) {
+ 			retval->pickrandom = atoi(p+1)-1; // xmms preloads the file
+@@ -2652,12 +2652,12 @@ static int ABC_Key(const char *p)
+ 	int i,j;
+ 	char c[8];
+ 	const char *q;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	q = p;
+ 	memset(c, 0, 8);
+ 	for( i=0; i<8 && *p && *p != ']'; p++ ) {
+-		if( isspace(*p) ) {
+-			while( isspace(*p) ) p++;
++		if( isspace(static_cast<unsigned char>(*p)) ) {
++			while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 			if( strncasecmp(p, "min", 3) && strncasecmp(p, "maj", 3) )
+ 				break;
+ 		}
+@@ -2687,9 +2687,9 @@ static int ABC_Key(const char *p)
+ 
+ static char *abc_skip_word(char *p)
+ {
+-	while( isspace(*p) ) p++;
+-	while( *p && !isspace(*p) && *p != ']') p++;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
++	while( *p && !isspace(static_cast<unsigned char>(*p)) && *p != ']') p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	return p;
+ }
+ 
+@@ -2798,7 +2798,7 @@ static void abc_setup_chordnames()
+ static int abc_MIDI_getnumber(const char *p)
+ {
+ 	int n;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	abc_getnumber(p, &n);
+ 	if( n < 0 )   n = 0;
+ 	if( n > 127 ) n = 127;
+@@ -2808,7 +2808,7 @@ static int abc_MIDI_getnumber(const char *p)
+ static int abc_MIDI_getprog(const char *p)
+ {
+ 	int n;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	abc_getnumber(p, &n);
+ 	if( n < 1 )   n = 1;
+ 	if( n > 128 ) n = 128;
+@@ -2819,32 +2819,32 @@ static int abc_MIDI_getprog(const char *p)
+ static void abc_MIDI_drone(const char *p, int *gm, int *ptch, int *vol)
+ {
+ 	int i;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	p += abc_getnumber(p, &i);
+ 	i++;	// adjust for 1..128
+ 	if( i>0 && i < 129 )
+ 		*gm = i;
+ 	else
+ 		*gm = 71;	// bassoon
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	p += abc_getnumber(p, &i);
+ 	if( i>0 && i < 127 )
+ 		ptch[0] = i;
+ 	else
+ 		ptch[0] = 45;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	p += abc_getnumber(p, &i);
+ 	if( i>0 && i < 127 )
+ 		ptch[1] = i;
+ 	else
+ 		ptch[1] = 33;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	p += abc_getnumber(p, &i);
+ 	if( i>0 && i < 127 )
+ 		vol[0] = i;
+ 	else
+ 		vol[0] = 80;
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	p += abc_getnumber(p, &i);
+ 	if( i>0 && i < 127 )
+ 		vol[1] = i;
+@@ -2869,8 +2869,8 @@ static void abc_MIDI_channel(const char *p, ABCTRACK *tp, ABCHANDLE *h)
+ {
+ 	int i1, i2;
+ 	i1 = tp? tp->vno: 1;
+-	for( ; *p && isspace(*p); p++ ) ;
+-	if( isdigit(*p) ) {
++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
++	if( isdigit(static_cast<unsigned char>(*p)) ) {
+ 		p += abc_getnumber(p, &i2);
+ 		if( i2 >= 1 && i2 <= 16 )
+ 			abc_chan_to_tracks(h, i1, i2); // we start at 1
+@@ -2894,11 +2894,11 @@ static void abc_MIDI_program(const char *p, ABCTRACK *tp, ABCHANDLE *h)
+ {
+ 	int i1, i2;
+ 	i1 = tp? tp->vno: 1;
+-	for( ; *p && isspace(*p); p++ ) ;
+-	if( isdigit(*p) ) {
++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
++	if( isdigit(static_cast<unsigned char>(*p)) ) {
+ 		p += abc_getnumber(p, &i2);
+-		for( ; *p && isspace(*p); p++ ) ;
+-		if( isdigit(*p) ) {
++		for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
++		if( isdigit(static_cast<unsigned char>(*p)) ) {
+ 			i1 = i2;
+ 			abc_getnumber(p, &i2);
+ 		}
+@@ -2919,25 +2919,25 @@ static void abc_mute_voice(ABCHANDLE *h, ABCTRACK *tp, int m)
+ static void abc_MIDI_voice(const char *p, ABCTRACK *tp, ABCHANDLE *h)
+ {
+ 	int i1, i2;
+-	for( ; *p && isspace(*p); p++ ) ;
++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 	if( strncmp(p,"instrument=",11) && strncmp(p,"mute",4) ) {
+ 		tp = abc_locate_track(h, p, 0);
+-		for( ; *p && !isspace(*p); p++ ) ;
+-		for( ; *p && isspace(*p); p++ ) ;
++		for( ; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) ;
++		for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 	}
+ 	i1 = tp? tp->vno: 1;
+ 	i2 = 0;
+-	if( !strncmp(p,"instrument=",11) && isdigit(p[11]) ) {
++	if( !strncmp(p,"instrument=",11) && isdigit(static_cast<unsigned char>(p[11])) ) {
+ 		p += 11;
+ 		p += abc_getnumber(p, &i2);
+-		for( ; *p && isspace(*p); p++ ) ;
+-		if( !strncmp(p,"bank=",5) && isdigit(p[5]) ) {
+-			for( ; *p && !isspace(*p); p++ ) ;
+-			for( ; *p && isspace(*p); p++ ) ;
++		for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
++		if( !strncmp(p,"bank=",5) && isdigit(static_cast<unsigned char>(p[5])) ) {
++			for( ; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) ;
++			for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 		}
+ 	}
+ 	if( tp ) abc_mute_voice(h,tp,0);
+-	if( !strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || isspace(p[4])) ) {
++	if( !strncmp(p,"mute",4) && (p[4]=='\0' || p[4]=='%' || isspace(static_cast<unsigned char>(p[4]))) ) {
+ 		if( tp ) abc_mute_voice(h,tp,1);
+ 	}
+ 	abc_instr_to_tracks(h, i1, i2); // starts already at 1 (draft 4.0)
+@@ -2949,7 +2949,7 @@ static void abc_MIDI_chordname(const char *p)
+ 	char name[20];
+ 	int i;
+ 
+-	for(; *p && isspace(*p); p++)
++	for(; *p && isspace(static_cast<unsigned char>(*p)); p++)
+ 		;
+ 	i = 0;
+ 	while ((i < 19) && (*p != ' ') && (*p != '\0')) {
+@@ -2965,8 +2965,8 @@ static void abc_MIDI_chordname(const char *p)
+ 		int notes[6];
+ 		i = 0;
+ 		memset(notes, 0, sizeof(notes));
+-		while ((i < 6) && isspace(*p)) {
+-			for(; *p && isspace(*p); p++)
++		while ((i < 6) && isspace(static_cast<unsigned char>(*p))) {
++			for(; *p && isspace(static_cast<unsigned char>(*p)); p++)
+ 				;
+ 			p += abc_getnumber(p, &notes[i]);
+ 			i = i + 1;
+@@ -2981,21 +2981,21 @@ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
+ {
+ 	char *q;
+ 	int i, n, m, len;
+-	while( isspace(*p) ) p++;
+-	if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2;
+-	if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
++	if( !strncmp(p,"on",2) && (isspace(static_cast<unsigned char>(p[2])) || p[2] == '\0') ) return 2;
++	if( !strncmp(p,"off",3) && (isspace(static_cast<unsigned char>(p[3])) || p[3] == '\0') ) return 1;
+ 	n = 0; len = 0;
+-	for( q = h->drum; *p && !isspace(*p); p++ ) {
++	for( q = h->drum; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) {
+ 		if( !strchr("dz0123456789",*p) ) break;
+ 		*q++ = *p; len++;
+-		if( !isdigit(*p) && len < (int)sizeof(h->drum)-1 ) {
+-			if( !isdigit(p[1]) ) { *q++ = '1'; len ++; }
++		if( !isdigit(static_cast<unsigned char>(*p)) && len < (int)sizeof(h->drum)-1 ) {
++			if( !isdigit(static_cast<unsigned char>(p[1])) ) { *q++ = '1'; len ++; }
+ 			n++; // count the silences too....
+ 		}
+ 		if (len >= (int)sizeof(h->drum)-1) {
+ 			// consume the rest of the input
+ 			// definitely enough "drum last state" stored.
+-			while ( *p && !isspace(*p) ) p++;
++			while ( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
+ 			break;
+ 		}
+ 	}
+@@ -3003,10 +3003,10 @@ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
+ 	q = h->drumins;
+ 	for( i = 0; i<n; i++ ) {
+ 		if( h->drum[i*2] == 'd' ) {
+-			while( *p && isspace(*p) ) p++;
+-			if( !isdigit(*p) ) {
++			while( *p && isspace(static_cast<unsigned char>(*p)) ) p++;
++			if( !isdigit(static_cast<unsigned char>(*p)) ) {
+ 				m = 0;
+-				while( *p && !isspace(*p) ) p++;
++				while( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
+ 			}
+ 			else
+ 				p += abc_getnumber(p,&m);
+@@ -3017,10 +3017,10 @@ static int abc_MIDI_drum(const char *p, ABCHANDLE *h)
+ 	q = h->drumvol;
+ 	for( i = 0; i<n; i++ ) {
+ 		if( h->drum[i*2] == 'd' ) {
+-			while( *p && isspace(*p) ) p++;
+-			if( !isdigit(*p) ) {
++			while( *p && isspace(static_cast<unsigned char>(*p)) ) p++;
++			if( !isdigit(static_cast<unsigned char>(*p)) ) {
+ 				m = 0;
+-				while( *p && !isspace(*p) ) p++;
++				while( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
+ 			}
+ 			else
+ 				p += abc_getnumber(p,&m);
+@@ -3036,17 +3036,17 @@ static int abc_MIDI_gchord(const char *p, ABCHANDLE *h)
+ {
+ 	char *q;
+ 	int len = 0;
+-	while( isspace(*p) ) p++;
+-	if( !strncmp(p,"on",2) && (isspace(p[2]) || p[2] == '\0') ) return 2;
+-	if( !strncmp(p,"off",3) && (isspace(p[3]) || p[3] == '\0') ) return 1;
+-	for( q = h->gchord; *p && !isspace(*p); p++ ) {
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
++	if( !strncmp(p,"on",2) && (isspace(static_cast<unsigned char>(p[2])) || p[2] == '\0') ) return 2;
++	if( !strncmp(p,"off",3) && (isspace(static_cast<unsigned char>(p[3])) || p[3] == '\0') ) return 1;
++	for( q = h->gchord; *p && !isspace(static_cast<unsigned char>(*p)); p++ ) {
+ 		if( !strchr("fbcz0123456789ghijGHIJ",*p) ) break;
+ 		*q++ = *p; len++;
+-		if( !isdigit(*p) && len < (int)sizeof(h->gchord)-1 && !isdigit(p[1]) ) { *q++ = '1'; len ++; }
++		if( !isdigit(static_cast<unsigned char>(*p)) && len < (int)sizeof(h->gchord)-1 && !isdigit(static_cast<unsigned char>(p[1])) ) { *q++ = '1'; len ++; }
+ 		if (len >= (int)sizeof(h->gchord)-1) {
+ 			// consume the rest of the input
+ 			// definitely enough "drum last state" stored.
+-			while ( *p && !isspace(*p) ) p++;
++			while ( *p && !isspace(static_cast<unsigned char>(*p)) ) p++;
+ 			break;
+ 		}
+ 	}
+@@ -3099,7 +3099,7 @@ static void abc_metric_gchord(ABCHANDLE *h, int mlen, int mdiv)
+ 
+ static void abc_MIDI_legato(const char *p, ABCTRACK *tp)
+ {
+-	for( ; *p && isspace(*p); p++ ) ;
++	for( ; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 	if( !strncmp(p,"off",3) ) tp->legato = 0;
+ 	else tp->legato = 1;
+ }
+@@ -3130,7 +3130,7 @@ static int abc_drum_steps(const char *dch)
+ 	const char *p;
+ 	int i=0;
+ 	for( p=dch; *p; p++ ) {
+-		if( isdigit(*p) ) i += *p - '0';;
++		if( isdigit(static_cast<unsigned char>(*p)) ) i += *p - '0';;
+ 	}
+ 	return i;
+ }
+@@ -3185,7 +3185,7 @@ static int abc_gchord_steps(const char *gch)
+ 	const char *p;
+ 	int i=0;
+ 	for( p=gch; *p; p++ )
+-		if( isdigit(*p) ) i += *p - '0';
++		if( isdigit(static_cast<unsigned char>(*p)) ) i += *p - '0';
+ 	return i;
+ }
+ 
+@@ -3231,7 +3231,7 @@ static void abc_add_gchord(ABCHANDLE *h, uint32_t tracktime, uint32_t bartime)
+ 	stime = (tracktime - etime) * steps;
+ 	rtime = 0;
+ 	while( rtime < stime ) {
+-		gnote = h->gchord[2*g];
++		gnote = static_cast<unsigned char>(h->gchord[2*g]);
+ 		glen  = h->gchord[2*g+1] - '0';
+ 		if( ++g == gsteps ) g = 0;
+ 		switch(gnote) {
+@@ -3313,7 +3313,7 @@ static void abc_MIDI_beat(ABCHANDLE *h, const char *p)
+ 	h->beat[2] = 110;
+ 	h->beat[3] = 1;
+ 	for( j=0; j<4; j++ ) {
+-		while( isspace(*p) ) p++;
++		while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 		if( *p ) {
+ 			p += abc_getnumber(p, &i);
+ 			if( i < 0   ) i = 0;
+@@ -3336,7 +3336,7 @@ static void abc_MIDI_beat(ABCHANDLE *h, const char *p)
+ // %%MIDI beatstring fppmpmp
+ static void abc_MIDI_beatstring(ABCHANDLE *h, const char *p)
+ {
+-	while( isspace(*p) ) p++;
++	while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 	if( h->beatstring ) _mm_free(h->allochandle, h->beatstring);
+ 	if( strlen(p) )
+ 		h->beatstring = DupStr(h->allochandle,p,strlen(p)+1);
+@@ -3483,47 +3483,47 @@ static void abc_recalculate_tracktime(ABCHANDLE *h) {
+ static void abc_MIDI_command(ABCHANDLE *h, char *p, char delim) {
+ 	int t;
+ 	// interpret some of the possibilitys
+-	if( !strncmp(p,"bassprog",8)    && isspace(p[8]) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1;
+-	if( !strncmp(p,"bassvol",7)     && isspace(p[7]) ) h->abcbassvol = abc_MIDI_getnumber(p+7);
+-	if( !strncmp(p,"beat",4)        && isspace(p[4]) ) abc_MIDI_beat(h, p+4);
+-	if( !strncmp(p,"beatstring",10) && isspace(p[10]) ) abc_MIDI_beatstring(h, p+4);
+-	if( !strncmp(p,"chordname",9)   && isspace(p[9]) ) abc_MIDI_chordname(p+9);
+-	if( !strncmp(p,"chordprog",9)   && isspace(p[9]) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1;
+-	if( !strncmp(p,"chordvol",8)    && isspace(p[8]) ) h->abcchordvol = abc_MIDI_getnumber(p+8);
+-	if( !strncmp(p,"drone",5)       && isspace(p[5]) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol);
+-	if( !strncmp(p,"droneoff",8)    && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->droneon = 0;
+-	if( !strncmp(p,"droneon",7)     && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->droneon = 1;
++	if( !strncmp(p,"bassprog",8)    && isspace(static_cast<unsigned char>(p[8])) ) h->abcbassprog = abc_MIDI_getprog(p+8)+1;
++	if( !strncmp(p,"bassvol",7)     && isspace(static_cast<unsigned char>(p[7])) ) h->abcbassvol = abc_MIDI_getnumber(p+7);
++	if( !strncmp(p,"beat",4)        && isspace(static_cast<unsigned char>(p[4])) ) abc_MIDI_beat(h, p+4);
++	if( !strncmp(p,"beatstring",10) && isspace(static_cast<unsigned char>(p[10])) ) abc_MIDI_beatstring(h, p+4);
++	if( !strncmp(p,"chordname",9)   && isspace(static_cast<unsigned char>(p[9])) ) abc_MIDI_chordname(p+9);
++	if( !strncmp(p,"chordprog",9)   && isspace(static_cast<unsigned char>(p[9])) ) h->abcchordprog = abc_MIDI_getprog(p+9)+1;
++	if( !strncmp(p,"chordvol",8)    && isspace(static_cast<unsigned char>(p[8])) ) h->abcchordvol = abc_MIDI_getnumber(p+8);
++	if( !strncmp(p,"drone",5)       && isspace(static_cast<unsigned char>(p[5])) ) abc_MIDI_drone(p+5, &h->dronegm, h->dronepitch, h->dronevol);
++	if( !strncmp(p,"droneoff",8)    && (p[8]=='\0' || p[8]==delim || isspace(static_cast<unsigned char>(p[8]))) ) h->droneon = 0;
++	if( !strncmp(p,"droneon",7)     && (p[7]=='\0' || p[7]==delim || isspace(static_cast<unsigned char>(p[7]))) ) h->droneon = 1;
+ 	t = h->drumon;
+-	if( !strncmp(p,"drum",4)        && isspace(p[4]) ) {
++	if( !strncmp(p,"drum",4)        && isspace(static_cast<unsigned char>(p[4])) ) {
+ 		h->drumon = abc_MIDI_drum(p+4, h);
+ 		if( h->drumon ) --h->drumon;
+ 		else h->drumon = t;
+ 	}
+-	if( !strncmp(p,"drumoff",7)     && (p[7]=='\0' || p[7]==delim || isspace(p[7])) ) h->drumon = 0;
+-	if( !strncmp(p,"drumon",6)      && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) h->drumon = 1;
++	if( !strncmp(p,"drumoff",7)     && (p[7]=='\0' || p[7]==delim || isspace(static_cast<unsigned char>(p[7]))) ) h->drumon = 0;
++	if( !strncmp(p,"drumon",6)      && (p[6]=='\0' || p[6]==delim || isspace(static_cast<unsigned char>(p[6]))) ) h->drumon = 1;
+ 	if( t != h->drumon ) {
+ 		if( h->drumon && !h->tpr ) h->tpr = h->track;
+ 		if( h->tpr ) abc_add_drum_sync(h, h->tpr, h->tracktime); // don't start drumming from the beginning of time!
+ 		if( h->tpr && !h->drumon ) h->tpr = NULL;
+ 	}
+ 	t = h->gchordon;
+-	if( !strncmp(p,"gchord",6)      && (p[6]=='\0' || p[6]==delim || isspace(p[6])) ) {
++	if( !strncmp(p,"gchord",6)      && (p[6]=='\0' || p[6]==delim || isspace(static_cast<unsigned char>(p[6]))) ) {
+ 		h->gchordon = abc_MIDI_gchord(p+6, h);
+ 		if( h->gchordon ) --h->gchordon;
+ 		else h->gchordon = t;
+ 	}
+-	if( !strncmp(p,"gchordoff",9)   && (p[9]=='\0' || p[9]==delim || isspace(p[9])) ) h->gchordon = 0;
+-	if( !strncmp(p,"gchordon",8)    && (p[8]=='\0' || p[8]==delim || isspace(p[8])) ) h->gchordon = 1;
++	if( !strncmp(p,"gchordoff",9)   && (p[9]=='\0' || p[9]==delim || isspace(static_cast<unsigned char>(p[9]))) ) h->gchordon = 0;
++	if( !strncmp(p,"gchordon",8)    && (p[8]=='\0' || p[8]==delim || isspace(static_cast<unsigned char>(p[8]))) ) h->gchordon = 1;
+ 	if( t != h->gchordon ) {
+ 		if( h->tpc ) abc_add_gchord_syncs(h, h->tpc, h->tracktime);
+ 	}
+-	if( !strncmp(p,"channel",7)     && isspace(p[7]) )
++	if( !strncmp(p,"channel",7)     && isspace(static_cast<unsigned char>(p[7])) )
+ 		abc_MIDI_channel(p+8, h->tp = abc_check_track(h, h->tp), h);
+-	if( !strncmp(p,"program",7)     && isspace(p[7]) )
++	if( !strncmp(p,"program",7)     && isspace(static_cast<unsigned char>(p[7])) )
+ 		abc_MIDI_program(p+8, h->tp = abc_check_track(h, h->tp), h);
+-	if( !strncmp(p,"voice",5)       && isspace(p[5]) )
++	if( !strncmp(p,"voice",5)       && isspace(static_cast<unsigned char>(p[5])) )
+ 		abc_MIDI_voice(p+6, h->tp = abc_check_track(h, h->tp), h);
+-	if( !strncmp(p,"legato",6)      && (p[6]=='\0' || p[6]==delim || isspace(p[6])) )
++	if( !strncmp(p,"legato",6)      && (p[6]=='\0' || p[6]==delim || isspace(static_cast<unsigned char>(p[6]))) )
+ 		abc_MIDI_legato(p+6, h->tp = abc_check_track(h, h->tp));
+ }
+ 
+@@ -3548,13 +3548,13 @@ static char *abc_continuated(ABCHANDLE *h, MMFILE *mmf, char *p) {
+ 				abc_message("line not properly continued\n%s", p1);
+ 				return p1;
+ 			}
+-			while( *pm && isspace(*pm) ) ++pm;
++			while( *pm && isspace(static_cast<unsigned char>(*pm)) ) ++pm;
+ 			if( !strncmp(pm,"%%",2) ) {
+-				for( p2 = pm+2; *p2 && isspace(*p2); p2++ ) ;
+-				if( !strncmp(p2,"MIDI",4) && (p2[4]=='=' || isspace(p2[4])) ) {
+-					for( p2+=5; *p2 && isspace(*p2); p2++ ) ;
++				for( p2 = pm+2; *p2 && isspace(static_cast<unsigned char>(*p2)); p2++ ) ;
++				if( !strncmp(p2,"MIDI",4) && (p2[4]=='=' || isspace(static_cast<unsigned char>(p2[4]))) ) {
++					for( p2+=5; *p2 && isspace(static_cast<unsigned char>(*p2)); p2++ ) ;
+ 					if( *p2 == '=' )
+-						for( p2+=1; *p2 && isspace(*p2); p2++ ) ;
++						for( p2+=1; *p2 && isspace(static_cast<unsigned char>(*p2)); p2++ ) ;
+ 					abc_MIDI_command(h,p2,'%');
+ 				}
+ 				continued = 1;
+@@ -3685,7 +3685,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 		abcxcount = 0;
+ 		mmfseek(mmfile,0,SEEK_SET);
+ 		while ((line=abc_gets(h, mmfile)) != NULL) {
+-			for( p=line; isspace(*p); p++ ) ;
++			for( p=line; isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 			if( !strncmp(p,"X:",2) ) abcxcount++;
+ 		}
+ 		if( abcxcount == 0 )
+@@ -3699,7 +3699,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 		mmsp--;
+ 		while ((line=abc_gets(h, mmstack[mmsp])) != NULL) {
+ 			char blankline[3] = "% ";
+-			for( p=line; isspace(*p); p++ ) ;
++			for( p=line; isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 			switch(abcstate) {
+ 				case INSKIPFORX:
+ 					if( !strncmp(p,"X:",2) ) {
+@@ -3711,7 +3711,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 					if( !strncmp(p,"X:",2) ) {
+ 						abcstate = INHEAD;
+ 						memset(m_szNames[0], 0, 32);
+-						for( p+=2; isspace(*p); p++ ) ;
++						for( p+=2; isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 						abcxnumber = atoi(p);
+ 						abchornpipe = 0;
+ 						h->droneon = 0;
+@@ -3792,8 +3792,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 						break;
+ 					}
+ 					if( !strncmp(p,"R:",2) ) {
+-						for( p+=2; isspace(*p); p++ ) ;
+-						if( !strncmp(p,"hornpipe",8) && (isspace(p[8]) || p[8]=='\0') ) abchornpipe = 1;
++						for( p+=2; isspace(static_cast<unsigned char>(*p)); p++ ) ;
++						if( !strncmp(p,"hornpipe",8) && (isspace(static_cast<unsigned char>(p[8])) || p[8]=='\0') ) abchornpipe = 1;
+ 						else abchornpipe = 0;
+ 						break;
+ 					}
+@@ -3980,8 +3980,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 				p[1]= '%';
+ 			}
+ 			if( !strncmp(p,"%%",2) ) {
+-				for( p+=2; *p && isspace(*p); p++ ) ;
+-				if( !strncmp(p,"abc-include",11) && isspace(p[11]) ) {
++				for( p+=2; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
++				if( !strncmp(p,"abc-include",11) && isspace(static_cast<unsigned char>(p[11])) ) {
+ 					for( t=12; isspace(p[t]); t++ ) ;
+ 					if( p[t] ) {
+ 						mmsp++;
+@@ -3998,10 +3998,10 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 					}
+ 					else abc_message("failure: abc-include missing file name, %s", p);
+ 				}
+-				if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) && abcstate != INSKIPFORX ) {
+-					for( p+=5; *p && isspace(*p); p++ ) ;
++				if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(static_cast<unsigned char>(p[4]))) && abcstate != INSKIPFORX ) {
++					for( p+=5; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 					if( *p == '=' )
+-						for( p+=1; *p && isspace(*p); p++ ) ;
++						for( p+=1; *p && isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 					abc_MIDI_command(h,p,'%');
+ 					if( h->tp ) abcnolegato = !h->tp->legato;
+ 					if( !abcnolegato ) abcnoslurs = 0;
+@@ -4034,7 +4034,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 							partpat[global_part - 'A'][1] = t;
+ 						// give every new coming abcevent the desired part indication
+ 						while( p[2]==' ' || p[2]=='.' ) p++;	// skip blancs and dots
+-						if( isupper(p[2]) )
++						if( isupper(static_cast<unsigned char>(p[2])) )
+ 							global_part = p[2];
+ 						else
+ 							global_part = ' ';
+@@ -4073,7 +4073,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 					ch0 = ' ';
+ 					pp = 0;
+ 					while (*p && (ch = *p++) != '\0') {
+-						if( !pp && isalpha(ch) && *p != ':' ) { // maybe a macro
++						if( !pp && isalpha(static_cast<unsigned char>(ch)) && *p != ':' ) { // maybe a macro
+ 							for( mp=h->umacro; mp; mp=mp->next ) {
+ 								if( ch == mp->name[0] ) {
+ 									pp = p;
+@@ -4131,8 +4131,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 										else
+ 											partpat[global_part - 'A'][1] = t;
+ 										// give every new coming abcevent the desired part indication
+-										while( isspace(p[2]) || p[2]=='.' ) p++;	// skip blancs and dots
+-										if( isupper(p[2]) )
++										while( isspace(static_cast<unsigned char>(p[2])) || p[2]=='.' ) p++;	// skip blancs and dots
++										if( isupper(static_cast<unsigned char>(p[2])) )
+ 											global_part = p[2];
+ 										else
+ 											global_part = ' ';
+@@ -4152,11 +4152,11 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 									break;
+ 								}
+ 								if( !strncmp(p,"I:",2) ) { // interpret some of the possibilitys
+-									for( p += 2; isspace(*p); p++ ) ;
+-									if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(p[4])) ) { // interpret some of the possibilitys
+-										for( p += 4; isspace(*p); p++ ) ;
++									for( p += 2; isspace(static_cast<unsigned char>(*p)); p++ ) ;
++									if( !strncmp(p,"MIDI",4) && (p[4]=='=' || isspace(static_cast<unsigned char>(p[4]))) ) { // interpret some of the possibilitys
++										for( p += 4; isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 										if( *p == '=' )
+-											for( p += 1; isspace(*p); p++ ) ;
++											for( p += 1; isspace(static_cast<unsigned char>(*p)); p++ ) ;
+ 										abc_MIDI_command(h, p, ']');
+ 										if( h->tp ) abcnolegato = !h->tp->legato;
+ 										if( !abcnolegato ) abcnoslurs = 0;
+@@ -4235,7 +4235,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 									notelen *= cnotelen;
+ 									notediv *= cnotediv;
+ 									tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
+-									while( isspace(*p) ) p++;	// allow spacing in broken rithm notation
++									while( isspace(static_cast<unsigned char>(*p)) ) p++;	// allow spacing in broken rithm notation
+ 									p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
+ 									thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
+ 									if( abcfermata ) {
+@@ -4278,7 +4278,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 									if( abceffoper != 255 ) abceffect = none;
+ 									break;
+ 								}
+-								if( isdigit(*p) ) {	// different endings in repeats [i,j,n-r,s,...
++								if( isdigit(static_cast<unsigned char>(*p)) ) {	// different endings in repeats [i,j,n-r,s,...
+ 									h->tp = abc_check_track(h, h->tp);
+ 									abc_add_partbreak(h, h->tp, h->tracktime);
+ 									p += abc_getnumber(p, &notelen);
+@@ -4304,7 +4304,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 								break;
+ 							case '(':	// slurs follow or some tuplet (duplet, triplet etc.)
+ 								abcto = 0;
+-								if( isdigit(*p) ) {
++								if( isdigit(static_cast<unsigned char>(*p)) ) {
+ 									p += abc_getnumber(p,&tupletp);
+ 									tupletr = tupletp;	// ABC draft 2.0 (4.13): if r is not given it defaults to p
+ 									switch( tupletp ) {	// ABC draft 2.0 (4.13): q defaults depending on p and time signature
+@@ -4323,10 +4323,10 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 									}
+ 									if( *p==':' ) {
+ 										p++;
+-										if( isdigit(*p) ) p += abc_getnumber(p,&tupletq);
++										if( isdigit(static_cast<unsigned char>(*p)) ) p += abc_getnumber(p,&tupletq);
+ 										if( *p==':' ) {
+ 											p++;
+-											if( isdigit(*p) ) p += abc_getnumber(p,&tupletr);
++											if( isdigit(static_cast<unsigned char>(*p)) ) p += abc_getnumber(p,&tupletr);
+ 										}
+ 									}
+ 								}
+@@ -4375,7 +4375,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 								sprintf(barsig, "%s%s", sig[abckey], sig[abckey]);	// reset the key signature
+ 								bartime = h->tracktime;
+ 								if( h->tp && h->tp->vpos ) h->tp = abc_locate_track(h, h->tp->v, 0); // reset from voice overlay
+-								if( isdigit(*p) ) {	// different endings in repeats |i,j,n-r,s,...
++								if( isdigit(static_cast<unsigned char>(*p)) ) {	// different endings in repeats |i,j,n-r,s,...
+ 									h->tp = abc_check_track(h, h->tp);
+ 									abc_add_partbreak(h, h->tp, h->tracktime);
+ 									p += abc_getnumber(p, &notelen);
+@@ -4426,7 +4426,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 								}
+ 								break;
+ 							case '"':	// chord notation
+-								if( !strchr("_^<>@", *p) && !isdigit(*p) ) { // if it's not a annotation string
++								if( !strchr("_^<>@", *p) && !isdigit(static_cast<unsigned char>(*p)) ) { // if it's not a annotation string
+ 									h->tp = abc_check_track(h, h->tp);
+ 									if( !h->tpc ) h->tpc = abc_locate_track(h, h->tp->v, 0);
+  									if( h->tp == h->tpc ) abc_add_chord(p, h, h->tpc, h->tracktime); // only do chords for one voice
+@@ -4443,8 +4443,8 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 										abcto = -1;
+ 									}
+ 									else
+-										if( !isspace(*p) ) abcto = 0;
+-									if( !strncasecmp(p,"to",2) && (isspace(p[2]) || p[2] == '"') ) abcto = 1;
++										if( !isspace(static_cast<unsigned char>(*p)) ) abcto = 0;
++									if( !strncasecmp(p,"to",2) && (isspace(static_cast<unsigned char>(p[2])) || p[2] == '"') ) abcto = 1;
+ 								}
+ 								if( !ch ) abcstate = INSKIPFORQUOTE;
+ 								break;
+@@ -4665,7 +4665,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 										h->tp->tienote = h->tp->tail;
+ 									}
+ 									tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
+-									while( isspace(*p) ) p++;	// allow spacing in broken rithm notation
++									while( isspace(static_cast<unsigned char>(*p)) ) p++;	// allow spacing in broken rithm notation
+ 									p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
+ 									thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
+ 									if( abcfermata ) {
+@@ -4699,7 +4699,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 									abc_track_clear_tiednote(h);
+ 									p += abc_notelen(p, &notelen, &notediv);
+ 									tupletr = abc_tuplet(&notelen, &notediv, tupletp, tupletq, tupletr);
+-									while( isspace(*p) ) p++;	// allow spacing in broken rithm notation
++									while( isspace(static_cast<unsigned char>(*p)) ) p++;	// allow spacing in broken rithm notation
+ 									p += abc_brokenrithm(p, &notelen, &notediv, &brokenrithm, abchornpipe);
+ 									thistime = notelen_notediv_to_ticks(h->speed, notelen*snotelen, notediv*snotediv);
+ 									if( abcfermata ) {
+@@ -4752,7 +4752,7 @@ BOOL CSoundFile::ReadABC(const uint8_t *lpStream, DWORD dwMemLength)
+ 									abcarpeggio = 0;
+ 									break;
+ 								}
+-								if( isalpha(ch) && *p==':' ) {
++								if( isalpha(static_cast<unsigned char>(ch)) && *p==':' ) {
+ 									// some unprocessed field line?
+ 									while( *p ) p++;	// skip it
+ 									break;
+diff --git a/src/load_mid.cpp b/src/load_mid.cpp
+index fe02f5e4..749b5d0c 100644
+--- a/src/load_mid.cpp
++++ b/src/load_mid.cpp
+@@ -1198,7 +1198,7 @@ BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength)
+ 	if (h->miditracks == 0) goto ErrorCleanup;
+ 
+ 	p = (BYTE *)getenv(ENV_MMMID_SPEED);
+-	if( p && isdigit(*p) && p[0] != '0' && p[1] == '\0' ) {
++	if( p && isdigit(static_cast<unsigned char>(*p)) && p[0] != '0' && p[1] == '\0' ) {
+ 		// transform speed
+ 		t = *p - '0';
+ 		h->speed *= t;
+diff --git a/src/load_pat.cpp b/src/load_pat.cpp
+index fe787311..dfa640e5 100644
+--- a/src/load_pat.cpp
++++ b/src/load_pat.cpp
+@@ -392,31 +392,31 @@ void pat_init_patnames(void)
+ 			_mm_fgets(mmcfg, line, PATH_MAX);
+ 			while( !_mm_feof(mmcfg) ) {
+ 			p = line;
+-			while ( isspace(*p) ) p ++;
+-			if( isdigit(p[0]) ) {
++			while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
++			if( isdigit(static_cast<unsigned char>(p[0])) ) {
+ 				// get pat number
+ 				i = atoi(p);
+-				while ( isdigit(*p) ) p ++;
+-				while ( isspace(*p) ) p ++;
++				while ( isdigit(static_cast<unsigned char>(*p)) ) p ++;
++				while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
+ 				// get pat file name
+ 				if( *p && i < MAXSMP && i >= 0 && *p != '#' ) {
+ 					q = isdrumset ? midipat[pat_gm_drumnr(i)-1] : midipat[i];
+ 					pfnlen = 0;
+-					while( *p && !isspace(*p) && *p != '#' && pfnlen < 128 ) {
++					while( *p && !isspace(static_cast<unsigned char>(*p)) && *p != '#' && pfnlen < 128 ) {
+ 						pfnlen ++;
+ 						*q++ = *p++;
+ 					}
+-					if( isblank(*p) && *(p+1) != '#' && pfnlen < 128 ) {
++					if( isblank(static_cast<unsigned char>(*p)) && *(p+1) != '#' && pfnlen < 128 ) {
+ 						*q++ = ':'; pfnlen ++;
+-						while( isspace(*p) ) {
+-							while( isspace(*p) ) p++;
++						while( isspace(static_cast<unsigned char>(*p)) ) {
++							while( isspace(static_cast<unsigned char>(*p)) ) p++;
+ 							if ( *p == '#' ) { // comment
+ 
+-							} else while( *p && !isspace(*p) && pfnlen < 128 ) {
++							} else while( *p && !isspace(static_cast<unsigned char>(*p)) && pfnlen < 128 ) {
+ 								pfnlen ++;
+ 								*q++ = *p++;
+ 							}
+-							if( isspace(*p) ) { *q++ = ' '; pfnlen++; }
++							if( isspace(static_cast<unsigned char>(*p)) ) { *q++ = ' '; pfnlen++; }
+ 						}
+ 					}
+ 					*q++ = '\0';
+@@ -429,11 +429,11 @@ void pat_init_patnames(void)
+ 			}
+ 			else if( !strncmp(p,"dir",3) )  {
+ 				p += 3;
+-				while ( isspace(*p) ) p ++;
++				while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
+ 				q = p + strlen(p);
+ 				if(q > p) {
+ 					--q;
+-					while ( q > p && isspace(*q) ) *(q--) = 0;
++					while ( q > p && isspace(static_cast<unsigned char>(*q)) ) *(q--) = 0;
+ 					strncpy(pathforpat, p, PATH_MAX - 1);
+ 					pathforpat[PATH_MAX - 1] = 0;
+ 				}
+@@ -441,9 +441,9 @@ void pat_init_patnames(void)
+ 			else if( !strncmp(p,"source",6) && nsources < 5 ) {
+ 				q = cfgsources[nsources];
+ 				p += 6;
+-				while ( isspace(*p) ) p ++;
++				while ( isspace(static_cast<unsigned char>(*p)) ) p ++;
+ 				pfnlen = 0;
+-				while ( *p && *p != '#' && !isspace(*p) && pfnlen < 128 ) {
++				while ( *p && *p != '#' && !isspace(static_cast<unsigned char>(*p)) && pfnlen < 128 ) {
+ 					pfnlen ++;
+ 					*q++ = *p++;
+ 				}
+@@ -857,7 +857,7 @@ static void PAT_ReadPatterns(MODCOMMAND *pattern[], WORD psize[], PATHANDLE *h,
+ 					i = tt2 - 16 * ((h->samples - 1 - ch) & 3);
+ 					if( tt1 < i ) {
+ 						t = t % 64;
+-						if( isalpha(tune[t]) ) {
++						if( isalpha(static_cast<unsigned char>(tune[t])) ) {
+ 							n   = pat_modnote(pat_note(tune[t]));
+ 							ins = ch + 1;
+ 							vol = 40;