diff --git a/README.txt b/README.txt index 889f9cb..4161fdd 100644 --- a/README.txt +++ b/README.txt @@ -192,6 +192,12 @@ also to Eliuk Blau for tracking down bugs in the memory management opcodes. * Version History +1.2.9 2011-08-28 Fixed a bug in glkop.c dispatching, to do with optional + array arguments, following a similar fix in Glulxe. + Glk array and string operations are now checked for memory + overflows (though not for ROM writing), following a similar + fix in Glulxe. + 1.2.8 2010-08-25 Fixed a problem with 'undo' when compiled as 64 bit, contributed by Ben Cressey. Fixed a sign problem for the @fceil opcode, following a diff --git a/git.h b/git.h index cd1f90e..8084aab 100644 --- a/git.h +++ b/git.h @@ -124,6 +124,7 @@ extern void startProgram (size_t cacheSize, enum IOMode ioMode); extern int git_init_dispatch(); extern glui32 git_perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist); extern strid_t git_find_stream_by_id(glui32 id); +extern glui32 git_find_id_for_stream(strid_t str); // git_search.c diff --git a/glkop.c b/glkop.c index f8c7ff0..ffda269 100644 --- a/glkop.c +++ b/glkop.c @@ -277,6 +277,16 @@ glui32 git_perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) directly -- instead of bothering with the whole prototype mess. */ + case 0x0047: /* stream_set_current */ + if (numargs != 1) + goto WrongArgNum; + glk_stream_set_current(git_find_stream_by_id(arglist[0])); + break; + case 0x0048: /* stream_get_current */ + if (numargs != 0) + goto WrongArgNum; + retval = git_find_id_for_stream(glk_stream_get_current()); + break; case 0x0080: /* put_char */ if (numargs != 1) goto WrongArgNum; @@ -297,6 +307,16 @@ glui32 git_perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) goto WrongArgNum; retval = glk_char_to_upper(arglist[0] & 0xFF); break; + case 0x0128: /* put_char_uni */ + if (numargs != 1) + goto WrongArgNum; + glk_put_char_uni(arglist[0]); + break; + case 0x012B: /* put_char_stream_uni */ + if (numargs != 2) + goto WrongArgNum; + glk_put_char_stream_uni(git_find_stream_by_id(arglist[0]), arglist[1]); + break; WrongArgNum: fatalError("Wrong number of arguments to Glk function."); @@ -306,7 +326,7 @@ glui32 git_perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) /* Go through the full dispatcher prototype foo. */ char *proto, *cx; dispatch_splot_t splot; - int argnum; + int argnum, argnum2; /* Grab the string. */ proto = gidispatch_prototype(funcnum); @@ -335,9 +355,11 @@ glui32 git_perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist) gidispatch_call(funcnum, argnum, splot.garglist); /* Phase 3. */ - argnum = 0; + argnum2 = 0; cx = proto; - unparse_glk_args(&splot, &cx, 0, &argnum, 0, 0); + unparse_glk_args(&splot, &cx, 0, &argnum2, 0, 0); + if (argnum != argnum2) + fatalError("Argument counts did not match."); break; } @@ -560,6 +582,12 @@ static void parse_glk_args(dispatch_splot_t *splot, char **proto, int depth, switch (typeclass) { case 'C': + /* This test checks for a giant array length, and cuts it down to + something reasonable. Future releases of this interpreter may + treat this case as a fatal error. */ + if (varglist[ix+1] > gEndMem || varglist[ix]+varglist[ix+1] > gEndMem) + varglist[ix+1] = gEndMem - varglist[ix]; + garglist[gargnum].array = (void*) AddressOfArray(varglist[ix]); gargnum++; ix++; @@ -568,6 +596,10 @@ static void parse_glk_args(dispatch_splot_t *splot, char **proto, int depth, cx++; break; case 'I': + /* See comment above. */ + if (varglist[ix+1] > gEndMem/4 || varglist[ix+1] > (gEndMem-varglist[ix])/4) + varglist[ix+1] = (gEndMem - varglist[ix]) / 4; + garglist[gargnum].array = CaptureIArray(varglist[ix], varglist[ix+1], passin); gargnum++; ix++; @@ -679,6 +711,8 @@ static void parse_glk_args(dispatch_splot_t *splot, char **proto, int depth, } else { cx++; + if (isarray) + ix++; } } } @@ -885,6 +919,8 @@ static void unparse_glk_args(dispatch_splot_t *splot, char **proto, int depth, } else { cx++; + if (isarray) + ix++; } } } @@ -916,6 +952,21 @@ strid_t git_find_stream_by_id(glui32 objid) return classes_get(1, objid); } +/* find_id_for_stream(): + The converse of find_stream_by_id(). + This is only needed in this file, so it's static. +*/ +glui32 git_find_id_for_stream(strid_t str) +{ + gidispatch_rock_t objrock; + + if (!str) + return 0; + + objrock = gidispatch_get_objrock(str, 1); + return ((classref_t *)objrock.ptr)->id; +} + /* Build a hash table to hold a set of Glk objects. */ static classtable_t *new_classtable(glui32 firstid) { diff --git a/help/glk.htm b/help/glk.htm index b4d3eb1..7c8546f 100644 --- a/help/glk.htm +++ b/help/glk.htm @@ -8,7 +8,7 @@
The complete Windows Glk package, including developer information, can be downloaded from the IF Archive's diff --git a/help/glulx.htm b/help/glulx.htm index 89d1040..0a11878 100644 --- a/help/glulx.htm +++ b/help/glulx.htm @@ -10,7 +10,7 @@
-Windows Git is based on Iain Merrick's Git 1.2.8, which is a complete implementation of version 3.1.2 +Windows Git is based on Iain Merrick's Git 1.2.9, which is a complete implementation of version 3.1.2 of the Glulx specification.
More information on Glulx is available from the Glulx web page: diff --git a/help/overview.htm b/help/overview.htm index 23190ef..4420318 100644 --- a/help/overview.htm +++ b/help/overview.htm @@ -4,7 +4,7 @@
-