mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-29 02:08:01 +03:00
Fix buffer overrun in LE/QE command
This commit is contained in:
+27
-19
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user