Patch for SegFault in function CheckMounts, src/cdrom/linux/SDL_syscdrom.c

Hi everyone,

SDL_Init(SDL_INIT_CDROM) segfaults reproducibly in function 'free()'
when running Mandrake/Mandriva. Looks like function CheckMounts tries to
free() memory allocated with alloca. Additionally, there was a code-path
leading to dereferencing and freeing NULL pointers.

My humble experience in many years: code size and bug count can be
reduced by almost 50% if one uses a mem_alloc that never fails (but
calls exit handler/registered cleanup code directly) and a mem_free that
simply ignores NULL pointers. If the OS doesn’t give you 40 bytes to
store a string, you are screwed anyway…

CU,
Elmar

P.S.: Sorry it’s not a true diff/patch, can’t get that to work :wink:

In src/cdrom/linux/SDL_syscdrom.c

replace
size_t mnt_type_len;
char *mnt_dev;
size_t mnt_dev_len;
with
char *mnt_dev;

replace
while ( (mntent=getmntent(mntfp)) != NULL ) {
mnt_type_len = SDL_strlen(mntent->mnt_type) + 1;
mnt_type = SDL_stack_alloc(char, mnt_type_len);
if (mnt_type == NULL)
continue; /* maybe you’ll get lucky next time. */

		mnt_dev_len = SDL_strlen(mntent->mnt_fsname) + 1;
		mnt_dev = SDL_stack_alloc(char, mnt_dev_len);
		if (mnt_dev == NULL) {
			SDL_stack_free(mnt_type);
			continue;
		}

		SDL_strlcpy(mnt_type, mntent->mnt_type, mnt_type_len);
		SDL_strlcpy(mnt_dev, mntent->mnt_fsname, mnt_dev_len);

		/* Handle "supermount" filesystem mounts */
		if ( SDL_strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) {
			tmp = SDL_strstr(mntent->mnt_opts, "fs=");
			if ( tmp ) {
				SDL_free(mnt_type);
				mnt_type = SDL_strdup(tmp + SDL_strlen("fs="));
				if ( mnt_type ) {
					tmp = SDL_strchr(mnt_type, ',');
					if ( tmp ) {
						*tmp = '\0';
					}
				}
			}
			tmp = SDL_strstr(mntent->mnt_opts, "dev=");
			if ( tmp ) {
				SDL_free(mnt_dev);
				mnt_dev = SDL_strdup(tmp + SDL_strlen("dev="));
				if ( mnt_dev ) {
					tmp = SDL_strchr(mnt_dev, ',');
					if ( tmp ) {
						*tmp = '\0';
					}
				}
			}
		}
		if ( SDL_strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) {

#ifdef DEBUG_CDROM
fprintf(stderr, “Checking mount path from %s: %s mounted on %s of %s\n”,
mtab, mnt_dev, mntent->mnt_dir, mnt_type);
#endif
if (CheckDrive(mnt_dev, mnt_type, &stbuf) > 0) {
AddDrive(mnt_dev, &stbuf);
}
}
SDL_stack_free(mnt_dev);
SDL_stack_free(mnt_type);

with
/* BUG FIX FOR malloc/free MISMATCH /
while ( (mntent=getmntent(mntfp)) != NULL ) {
if (!(mnt_type = SDL_strdup(mntent->mnt_type))) continue;
if (!(mnt_dev = SDL_strdup(mntent->mnt_type))) {
SDL_free(mnt_type);
continue;
}
/
Handle “supermount” filesystem mounts */
if ( SDL_strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) {
tmp = SDL_strstr(mntent->mnt_opts, “fs=”);
if ( tmp ) {
SDL_free(mnt_type);
mnt_type = SDL_strdup(tmp+3);
if ( mnt_type ) {
tmp = SDL_strchr(mnt_type, ‘,’);
if ( tmp ) {
*tmp = ‘\0’;
}
}
}
tmp = SDL_strstr(mntent->mnt_opts, “dev=”);
if ( tmp ) {
SDL_free(mnt_dev);
mnt_dev = SDL_strdup(tmp+4);
if ( mnt_dev ) {
tmp = SDL_strchr(mnt_dev, ‘,’);
if ( tmp ) {
*tmp = ‘\0’;
}
}
}
}
if (mnt_dev && mnt_type && SDL_strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) {
#ifdef DEBUG_CDROM
fprintf(stderr, “Checking mount path from %s: %s mounted on %s of %s\n”,
mtab, mnt_dev, mntent->mnt_dir, mnt_type);
#endif
if (CheckDrive(mnt_dev, mnt_type, &stbuf) > 0) {
AddDrive(mnt_dev, &stbuf);
}
}
if (mnt_dev) SDL_free(mnt_dev);
if (mnt_type) SDL_free(mnt_type);–
Elmar Krieger, PhD
YASARA Biosciences & CMBI Outstation Austria
Neue-Welt-Hoehe 13/b
A-8042 Graz
Austria/Europe

             Ww
           c(@@)c

================()==OUu============
=WHAT IF YASARA knows the answer?!=
=----- http://www.yasara.org -----=
=- http://www.cmbi.kun.nl/whatif -=
============OOo====================
() ()
/ /