Skip to content

Commit d48a355

Browse files
authored
Merge pull request #35 from lclevy/fix-adfgetcacheentry-crash
Fix adfGetCacheEntry() crashing on bad data
2 parents c57188a + 30323ca commit d48a355

File tree

8 files changed

+74
-11
lines changed

8 files changed

+74
-11
lines changed

regtests/Dumps/cache_crash.adf

880 KB
Binary file not shown.

regtests/Test/Makefile.am

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ AM_CFLAGS = -std=c99 -pedantic -Wall -Wextra \
99
check_PROGRAMS = \
1010
access \
1111
bootdisk \
12+
cache_crash \
1213
comment \
1314
del_test \
1415
dir_test \
@@ -135,6 +136,10 @@ access_SOURCES = access.c
135136
access_LDADD = $(ADFLIBS)
136137
access_DEPENDENCIES = $(top_builddir)/src/libadf.la
137138

139+
cache_crash_SOURCES = cache_crash.c
140+
cache_crash_LDADD = $(ADFLIBS)
141+
cache_crash_DEPENDENCIES = $(top_builddir)/src/libadf.la
142+
138143
comment_SOURCES = comment.c
139144
comment_LDADD = $(ADFLIBS)
140145
comment_DEPENDENCIES = $(top_builddir)/src/libadf.la

regtests/Test/bigdev.sh

+2
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ done
3838
echo "---------------------------------------------------"
3939
echo "${NFAILED} tests failed: ${FAILED}"
4040
echo "---------------------------------------------------"
41+
42+
[ ${NFAILED} -eq 0 ]

regtests/Test/cache_crash.c

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <stdio.h>
2+
#include "adflib.h"
3+
4+
/* verifies that Debian bug 862740 is fixed
5+
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=862740
6+
* Usage: ./cache_crash ../Dumps/cache_crash.adf
7+
*/
8+
int main(int argc, char *argv[]) {
9+
struct AdfDevice *dev;
10+
struct AdfVolume *vol;
11+
struct AdfList *list;
12+
BOOL ok = FALSE, true = TRUE;
13+
14+
if (argc <= 1) return 1;
15+
adfEnvInitDefault();
16+
if ((dev = adfMountDev(argv[1], TRUE))) {
17+
if ((vol = adfMount(dev, 0, TRUE))) {
18+
/* use dir cache (enables the crash) */
19+
adfChgEnvProp(PR_USEDIRC, &true);
20+
/* read all directory entries (crash happens here) */
21+
list = adfGetRDirEnt(vol, vol->curDirPtr, TRUE);
22+
/* success! we didn't crash */
23+
ok = TRUE;
24+
if (list) adfFreeDirList(list);
25+
adfUnMount(vol);
26+
}
27+
adfUnMountDev(dev);
28+
}
29+
adfEnvCleanUp();
30+
return ok ? 0 : 1;
31+
}

regtests/Test/cache_crash.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
3+
# common settings
4+
. ./common.sh
5+
6+
set -e
7+
8+
./cache_crash $DUMPS/cache_crash.adf

regtests/Test/floppy.sh

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ esac
1818

1919
for A_TEST in \
2020
bootdisk.sh \
21+
cache_crash.sh \
2122
del_test.sh \
2223
dir_test.sh \
2324
dir_test2.sh \
@@ -53,3 +54,5 @@ done
5354
echo "---------------------------------------------------"
5455
echo "${NFAILED} tests failed: ${FAILED}"
5556
echo "---------------------------------------------------"
57+
58+
[ ${NFAILED} -eq 0 ]

src/adf_cache.c

+22-8
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ struct AdfList * adfGetDirEntCache ( struct AdfVolume * const vol,
8686
adfFreeDirList(head);
8787
return NULL;
8888
}
89-
adfGetCacheEntry(&dirc, &offset, &caEntry);
89+
if (adfGetCacheEntry(&dirc, &offset, &caEntry) != RC_OK) {
90+
free(entry); adfFreeDirList(head);
91+
return NULL;
92+
}
9093

9194
/* converts a cache entry into a dir entry */
9295
entry->type = (int)caEntry.type;
@@ -140,13 +143,14 @@ struct AdfList * adfGetDirEntCache ( struct AdfVolume * const vol,
140143
* Returns a cache entry, starting from the offset p (the index into records[])
141144
* This offset is updated to the end of the returned entry.
142145
*/
143-
void adfGetCacheEntry ( const struct bDirCacheBlock * const dirc,
144-
int * const p,
145-
struct AdfCacheEntry * const cEntry )
146+
RETCODE adfGetCacheEntry ( const struct bDirCacheBlock * const dirc,
147+
int * const p,
148+
struct AdfCacheEntry * const cEntry )
146149
{
147150
int ptr;
148151

149152
ptr = *p;
153+
if (ptr > LOGICAL_BLOCK_SIZE - 26) return RC_ERROR; /* minimum cache entry length */
150154

151155
/*printf("p=%d\n",ptr);*/
152156

@@ -171,10 +175,15 @@ void adfGetCacheEntry ( const struct bDirCacheBlock * const dirc,
171175
/* cEntry->name = (char*)malloc(sizeof(char)*(cEntry->nLen+1));
172176
if (!cEntry->name)
173177
return;
174-
*/ memcpy(cEntry->name, dirc->records+ptr+24, cEntry->nLen);
178+
*/
179+
if (cEntry->nLen < 1 || cEntry->nLen > MAXNAMELEN) return RC_ERROR;
180+
if ((ptr + 24 + cEntry->nLen) > LOGICAL_BLOCK_SIZE) return RC_ERROR;
181+
memcpy(cEntry->name, dirc->records+ptr+24, cEntry->nLen);
175182
cEntry->name[(int)(cEntry->nLen)]='\0';
176183

177184
cEntry->cLen = dirc->records[ptr+24+cEntry->nLen];
185+
if (cEntry->cLen > MAXCMMTLEN) return RC_ERROR;
186+
if ((ptr+24+cEntry->nLen+1+cEntry->cLen) > LOGICAL_BLOCK_SIZE) return RC_ERROR;
178187
if (cEntry->cLen>0) {
179188
/* cEntry->comm =(char*)malloc(sizeof(char)*(cEntry->cLen+1));
180189
if (!cEntry->comm) {
@@ -190,6 +199,8 @@ void adfGetCacheEntry ( const struct bDirCacheBlock * const dirc,
190199
/* the starting offset of each record must be even (68000 constraint) */
191200
if ((*p%2)!=0)
192201
*p=(*p)+1;
202+
203+
return RC_OK;
193204
}
194205

195206

@@ -308,7 +319,8 @@ RETCODE adfDelFromCache ( struct AdfVolume * const vol,
308319
offset = 0; n = 0;
309320
while(n < dirc.recordsNb && !found) {
310321
oldOffset = offset;
311-
adfGetCacheEntry(&dirc, &offset, &caEntry);
322+
if (adfGetCacheEntry(&dirc, &offset, &caEntry) != RC_OK)
323+
return RC_ERROR;
312324
found = ( caEntry.header == (uint32_t) headerKey );
313325
if (found) {
314326
entryLen = offset-oldOffset;
@@ -383,7 +395,8 @@ RETCODE adfAddInCache ( struct AdfVolume * const vol,
383395
offset = 0; n = 0;
384396
/*printf("parent=%4ld\n",dirc.parent);*/
385397
while(n < dirc.recordsNb) {
386-
adfGetCacheEntry(&dirc, &offset, &caEntry);
398+
if (adfGetCacheEntry(&dirc, &offset, &caEntry) != RC_OK)
399+
return RC_ERROR;
387400
/*printf("*%4ld %2d %6ld %8lx %4d %2d:%02d:%02d %30s %22s\n",
388401
caEntry.header, caEntry.type, caEntry.size, caEntry.protect,
389402
caEntry.days, caEntry.mins/60, caEntry.mins%60,
@@ -473,7 +486,8 @@ RETCODE adfUpdateCache ( struct AdfVolume * const vol,
473486
while(n < dirc.recordsNb && !found) {
474487
oldOffset = offset;
475488
/* offset is updated */
476-
adfGetCacheEntry(&dirc, &offset, &caEntry);
489+
if (adfGetCacheEntry(&dirc, &offset, &caEntry) != RC_OK)
490+
return RC_ERROR;
477491
oLen = offset-oldOffset;
478492
sLen = oLen-nLen;
479493
/*printf("olen=%d nlen=%d\n",oLen,nLen);*/

src/adf_cache.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ struct AdfCacheEntry {
4848
};
4949

5050

51-
void adfGetCacheEntry ( const struct bDirCacheBlock * const dirc,
52-
int * const p,
53-
struct AdfCacheEntry * const cEntry );
51+
RETCODE adfGetCacheEntry ( const struct bDirCacheBlock * const dirc,
52+
int * const p,
53+
struct AdfCacheEntry * const cEntry );
5454

5555
int adfPutCacheEntry ( struct bDirCacheBlock * const dirc,
5656
const int * const p,

0 commit comments

Comments
 (0)