Fix buffer overrun in LE/QE command

This commit is contained in:
kichikuou
2022-08-28 08:43:18 +09:00
parent d508676c70
commit c8f9880efb
7 changed files with 104 additions and 104 deletions
+27 -19
View File
@@ -380,25 +380,31 @@ void commands2F23() {
void commands2F24() {
int type = sl_getc();
const char *file_name = sl_getString(0);
int *var = NULL, _var = 0;
int num = 0;
int var, cnt;
struct VarRef vref;
char *fname_utf8 = toUTF8(file_name);
switch(type) {
switch (type) {
case 0:
var = getCaliVariable();
num = getCaliValue();
sysVar[0] = save_load_var_with_file(fname_utf8, var, num);
getCaliArray(&vref);
var = vref.var;
cnt = getCaliValue();
sysVar[0] = load_vars_from_file(fname_utf8, &vref, cnt);
break;
case 1:
_var = getCaliValue();
num = getCaliValue();
sysVar[0] = save_load_str_with_file(fname_utf8, _var, num);
var = getCaliValue();
cnt = getCaliValue();
sysVar[0] = save_load_str_with_file(fname_utf8, var, cnt);
break;
default:
var = getCaliValue();
cnt = getCaliValue();
WARNING("Unknown LE command type %d\n", type);
break;
}
free(fname_utf8);
DEBUG_COMMAND("LE(new) %d, %s, %d, %d:\n", type, file_name, var, num);
DEBUG_COMMAND("LE(new) %d, %s, %d, %d:\n", type, file_name, var, cnt);
}
void commands2F25() {
@@ -483,29 +489,31 @@ void commands2F29() {
void commands2F2A() {
int type = sl_getc();
const char *file_name = sl_getString(0);
int *var, _var = 0, cnt;
int var, cnt;
struct VarRef vref;
char *fname_utf8 = toUTF8(file_name);
switch(type) {
case 0:
var = getCaliVariable();
getCaliArray(&vref);
var = vref.var;
cnt = getCaliValue();
sysVar[0] = save_save_var_with_file(fname_utf8, var, cnt);
sysVar[0] = save_vars_to_file(fname_utf8, &vref, cnt);
break;
case 1:
_var = getCaliValue();
cnt = getCaliValue();
sysVar[0] = save_save_str_with_file(fname_utf8, _var, cnt);
var = getCaliValue();
cnt = getCaliValue();
sysVar[0] = save_save_str_with_file(fname_utf8, var, cnt);
break;
default:
_var = getCaliValue();
cnt = getCaliValue();
var = getCaliValue();
cnt = getCaliValue();
WARNING("Unknown QE command\n");
break;
}
free(fname_utf8);
DEBUG_COMMAND("QE(new) %d, %s, %d, %d:\n", type, file_name, _var, cnt);
DEBUG_COMMAND("QE(new) %d, %s, %d, %d:\n", type, file_name, var, cnt);
}
void commands2F2B() {
+1 -1
View File
@@ -79,7 +79,7 @@ void commandDF() {
DEBUG_COMMAND("DF %p,%d,%d:\n", data_var, cnt, data);
if (data_var.page) {
int maxlen = varPage[data_var.page].size - data_var.index;
int maxlen = v_sliceSize(&data_var);
if (cnt > maxlen) {
WARNING("%03d:%05x: count exceeds array boundary (%d > %d)\n", sl_getPage(), sl_getIndex(), cnt, maxlen);
cnt = maxlen;
+13 -12
View File
@@ -109,30 +109,31 @@ void commandLT() {
void commandLE() {
int type = sl_getc();
const char *filename = sl_getString(':');
int *var, _var = 0;
int num;
int var, cnt;
struct VarRef vref;
char *fname_utf8 = toUTF8(filename);
switch(type) {
switch (type) {
case 0: /* T2 */
var = getCaliVariable();
num = getCaliValue();
sysVar[0] = save_load_var_with_file(fname_utf8, var, num);
getCaliArray(&vref);
var = vref.var;
cnt = getCaliValue();
sysVar[0] = load_vars_from_file(fname_utf8, &vref, cnt);
break;
case 1: /* 456 */
_var = getCaliValue();
num = getCaliValue();
sysVar[0] = save_load_str_with_file(fname_utf8, _var, num);
var = getCaliValue();
cnt = getCaliValue();
sysVar[0] = save_load_str_with_file(fname_utf8, var, cnt);
break;
default:
_var = getCaliValue();
num = getCaliValue();
var = getCaliValue();
cnt = getCaliValue();
WARNING("Unknown LE command %d\n", type);
break;
}
free(fname_utf8);
DEBUG_COMMAND("LE %d,%s,%d,%d:\n",type, filename, _var, num);
DEBUG_COMMAND("LE %d,%s,%d,%d:\n",type, filename, var, cnt);
}
void commandLL() {
+13 -11
View File
@@ -83,30 +83,32 @@ void commandQC() {
}
void commandQE() {
int type = sl_getc();
int type = sl_getc();
const char *filename = sl_getString(':');
int *var, _var = 0, cnt;
int var, cnt;
struct VarRef vref;
char *fname_utf8 = toUTF8(filename);
switch(type) {
switch (type) {
case 0:
var = getCaliVariable();
getCaliArray(&vref);
var = vref.var;
cnt = getCaliValue();
sysVar[0] = save_save_var_with_file(fname_utf8, var, cnt);
sysVar[0] = save_vars_to_file(fname_utf8, &vref, cnt);
break;
case 1:
_var = getCaliValue();
cnt = getCaliValue();
sysVar[0] = save_save_str_with_file(fname_utf8, _var, cnt);
var = getCaliValue();
cnt = getCaliValue();
sysVar[0] = save_save_str_with_file(fname_utf8, var, cnt);
break;
default:
_var = getCaliValue();
cnt = getCaliValue();
var = getCaliValue();
cnt = getCaliValue();
WARNING("Unknown QE command %d\n", type);
break;
}
free(fname_utf8);
WARN_SAVEERR("QE", sysVar[0]);
DEBUG_COMMAND("QE %d,%s,%d,%d:\n", type, filename, _var, cnt);
DEBUG_COMMAND("QE %d,%s,%d,%d:\n", type, filename, var, cnt);
}
+45 -59
View File
@@ -76,76 +76,62 @@ int save_delete_file(int index) {
return 1; /* とりあえず */
}
/* 指定ファイルへの変数の書き込み */
int save_save_var_with_file(char *fname_utf8, int *start, int cnt) {
int status = 0, size, i;
FILE *fp;
WORD *tmp;
tmp = (WORD *)malloc(cnt * sizeof(WORD));
if (tmp == NULL) {
WARNING("Out of memory\n");
// QE command
int save_vars_to_file(char *fname_utf8, struct VarRef *src, int cnt) {
// FIXME: System39.exe does not truncate existing file.
FILE *fp = fc_open(fname_utf8, 'w');
if (!fp)
return SAVE_SAVEERR;
if (cnt > v_sliceSize(src)) {
WARNING("QE: array size too small (size = %d, data count = %d)\n", v_sliceSize(src), cnt);
cnt = v_sliceSize(src);
}
for (i = 0; i < cnt; i++) {
tmp[i] = SDL_SwapLE16((WORD)start[i]);
int *p = v_resolveRef(src);
while (cnt--) {
fputc(*p & 0xff, fp);
fputc(*p >> 8, fp);
p++;
}
if (NULL == (fp = fc_open(fname_utf8, 'w'))) {
status = SAVE_SAVEERR; goto errexit;
}
size = fwrite(tmp, sizeof(WORD), cnt, fp);
if (size != cnt) {
status = SAVE_OTHERERR;
} else {
status = SAVE_SAVEOK0;
}
fclose(fp);
scheduleSync();
errexit:
free(tmp);
return status;
return SAVE_SAVEOK0;
}
/* 指定ファイルからの変数の読み込み */
int save_load_var_with_file(char *fname_utf8, int *start, int cnt) {
int status = 0, size, i;
FILE *fp;
WORD *tmp;
tmp = (WORD *)malloc(cnt * sizeof(WORD));
if (tmp == NULL) {
// LE command
int load_vars_from_file(char *fname_utf8, struct VarRef *dest, int cnt) {
FILE *fp = fc_open(fname_utf8, 'r');
if (!fp)
return SAVE_LOADERR;
WORD *tmp = malloc(cnt * sizeof(WORD));
if (!tmp) {
WARNING("Out of memory\n");
fclose(fp);
return SAVE_LOADERR;
}
if (NULL == (fp = fc_open(fname_utf8, 'r'))) {
status = SAVE_LOADERR; goto errexit;
}
size = fread(tmp, sizeof(WORD), cnt, fp);
size_t size = fread(tmp, sizeof(WORD), cnt, fp);
fclose(fp);
if (size != cnt) {
status = SAVE_LOADSHORTAGE;
} else {
status = SAVE_LOADOK;
}
for (i = 0; i < cnt; i++) {
start[i] = SDL_SwapLE16(tmp[i]);
WARNING("LE: data file too small (requested = %d, loaded = %d)", cnt, size);
cnt = size;
// NOTE: System39.exe never returns SAVE_LOADSHORTAGE (254).
}
fclose(fp);
errexit:
if (cnt > v_sliceSize(dest)) {
WARNING("LE: array size too small (size = %d, data count = %d)\n", v_sliceSize(dest), cnt);
cnt = v_sliceSize(dest);
}
int *start = v_resolveRef(dest);
for (int i = 0; i < cnt; i++)
start[i] = SDL_SwapLE16(tmp[i]);
free(tmp);
return status;
return SAVE_LOADOK;
}
@@ -265,8 +251,8 @@ int save_loadPartial(int no, struct VarRef *vref, int cnt) {
if (no >= SAVE_MAXNUMBER) {
return SAVE_SAVEERR;
}
cnt = min(cnt, varPage[vref->page].size - vref->index);
var = varPage[vref->page].value + vref->index;
cnt = min(cnt, v_sliceSize(vref));
var = v_resolveRef(vref);
saveTop = loadGameData(no, &status, &filesize);
if (saveTop == NULL) {
@@ -318,8 +304,8 @@ int save_savePartial(int no, struct VarRef *vref, int cnt) {
}
if (!varPage[vref->page].saveflag)
goto errexit;
cnt = min(cnt, varPage[vref->page].size - vref->index);
var = varPage[vref->page].value + vref->index;
cnt = min(cnt, v_sliceSize(vref));
var = v_resolveRef(vref);
saveTop = loadGameData(no, &status, &filesize);
if (saveTop == NULL)
+2 -2
View File
@@ -117,8 +117,8 @@ extern int save_saveAll(int no);
extern int save_loadPartial(int no, struct VarRef *vref, int cnt);
extern int save_savePartial(int no, struct VarRef *vref, int cnt);
extern int save_copyAll(int dstno, int srcno);
extern int save_save_var_with_file(char *fname_utf8, int *start, int cnt);
extern int save_load_var_with_file(char *fname_utf8, int *start, int cnt);
extern int save_vars_to_file(char *fname_utf8, struct VarRef *src, int cnt);
extern int load_vars_from_file(char *fname_utf8, struct VarRef *dest, int cnt);
extern int save_save_str_with_file(char *fname_utf8, int start, int cnt);
extern int save_load_str_with_file(char *fname_utf8, int start, int cnt);
extern BYTE* load_cg_with_file(char *fname_utf8, int *status, long *filesize);
+3
View File
@@ -50,6 +50,9 @@ extern double longVar[];
static inline int *v_resolveRef(struct VarRef *r) {
return varPage[r->page].value + r->index;
}
static inline int v_sliceSize(struct VarRef *r) {
return varPage[r->page].size - r->index;
}
const char *v_name(int var);
int *v_ref_indexed(int var, int index, struct VarRef *ref);