Singe now checks the validity of games before unpacking them.

This commit is contained in:
Scott Duensing 2023-11-17 20:12:33 -06:00
parent de6d5f1fe5
commit fd1a2951ff
3 changed files with 160 additions and 55 deletions

View file

@ -859,11 +859,20 @@ void unpackGames(void) {
struct archive_entry *entry; struct archive_entry *entry;
int flags; int flags;
int r; int r;
int x;
int count = 0; int count = 0;
bool ok; bool ok;
bool hasGamesDat;
const void *buff; const void *buff;
size_t size; size_t size;
la_int64_t offset; la_int64_t offset;
char *e;
char *gamesDat = NULL;
char *extension;
char *filename;
char *toplevel = NULL;
char *badFilenames[] = { "Framework.singe", 0 };
char *badExtensions[] = { "exe", "sh", "bat", "cmd", "index", 0 };
if (dir == NULL) utilDie("Could not open the current directory."); if (dir == NULL) utilDie("Could not open the current directory.");
@ -872,10 +881,99 @@ void unpackGames(void) {
if (utilStricmp(utilGetFileExtension(de->d_name), "game") == 0) { if (utilStricmp(utilGetFileExtension(de->d_name), "game") == 0) {
showHeader(); showHeader();
count++; count++;
utilSay(">>> Unpacking Game: %s", de->d_name);
// https://github.com/libarchive/libarchive/wiki/Examples#user-content-A_Complete_Extractor
ok = true; ok = true;
hasGamesDat = false;
// Look through archive for things I've told people NOT to ship!
// https://github.com/libarchive/libarchive/wiki/Examples#user-content-List_contents_of_Archive_stored_in_File
a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
r = archive_read_open_filename(a, de->d_name, 10240);
if (r != ARCHIVE_OK) {
utilSay("!!! Cannot read game: %s", de->d_name);
ok = false;
} else {
while (archive_read_next_header(a, &entry) == ARCHIVE_OK && ok) {
e = (char *)archive_entry_pathname(entry);
filename = utilGetLastPathComponent(e);
extension = utilGetFileExtension(e);
// Do we have a top level folder name yet?
if (toplevel == NULL) {
// No. Is this a folder?
if (strstr(e, "/") == NULL) {
// No. BAD! No files in the root!
ok = false;
utilSay("!!! Game has files in root: %s", de->d_name);
} else {
// Remember this folder.
toplevel = strdup(e);
gamesDat = utilCreateString("%sgames.dat", toplevel);
}
} else {
// Yes, we have a top level. Is this entry inside it?
if (!utilStartsWith(e, toplevel)) {
// No. BAD! Everything has to be in the top level.
ok = false;
if (strstr(e, "/") == NULL) {
utilSay("!!! Game has files in root: %s", de->d_name);
} else {
utilSay("!!! Game has multiple top level directories: %s", de->d_name);
}
utilSay("[%s] %s", toplevel, e);
} else {
// Is this a forbidden file?
x = 0;
while (badFilenames[x] != NULL && ok) {
if (utilStricmp(filename, badFilenames[x]) == 0) {
ok = false;
utilSay("!!! Game has %s: %s", badFilenames[x], de->d_name);
}
x++;
}
// Is this a forbidden extension?
x = 0;
while (badExtensions[x] != NULL && ok) {
if (utilStricmp(extension, badExtensions[x]) == 0) {
ok = false;
utilSay("!!! Game has %s file: %s", badExtensions[x], de->d_name);
}
x++;
}
// No extension, starts with 'singe' - could be unix binary.
if (ok && strlen(extension) == 0 && utilStartsWith(filename, "singe")) {
ok = false;
utilSay("!!! Game has singe file: %s", de->d_name);
}
// Is this games.dat?
if (ok && !hasGamesDat && utilStricmp(e, gamesDat) == 0) hasGamesDat = true;
}
}
//utilSay("%s [%s] %s", filename, extension, e);
archive_read_data_skip(a);
}
r = archive_read_free(a);
if (toplevel != NULL) {
free(toplevel);
toplevel = NULL;
}
if (gamesDat != NULL) {
free(gamesDat);
gamesDat = NULL;
}
// Did we get a games.dat?
if (ok && !hasGamesDat) {
ok = false;
utilSay("!!! Game has no games.dat: %s", de->d_name);
}
}
// Unpack it!
if (ok) {
utilSay(">>> Unpacking Game: %s", de->d_name);
// https://github.com/libarchive/libarchive/wiki/Examples#user-content-A_Complete_Extractor
flags = ARCHIVE_EXTRACT_TIME; flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL; flags |= ARCHIVE_EXTRACT_ACL;
@ -933,9 +1031,11 @@ void unpackGames(void) {
archive_write_free(ext); archive_write_free(ext);
if (ok) unlink(de->d_name); if (ok) unlink(de->d_name);
}
} } // if ok
} } // if extension is game
} // if it's a file
} // while files
if (count > 0) utilSay(""); if (count > 0) utilSay("");

View file

@ -442,6 +442,10 @@ void utilSay(char *fmt, ...) {
} }
bool utilStartsWith(char *string, char *start) {
return strncmp(start, string, strlen(start)) == 0;
}
int utilStricmp(char *a, char *b) { int utilStricmp(char *a, char *b) {
for (;; a++, b++) { for (;; a++, b++) {

View file

@ -53,6 +53,7 @@ char *utilReadFile(char *filename, size_t *bytes);
char *utilReadLine(char *haystack, size_t length, char **offset); char *utilReadLine(char *haystack, size_t length, char **offset);
void utilRedirectConsole(void); void utilRedirectConsole(void);
void utilSay(char *fmt, ...); void utilSay(char *fmt, ...);
bool utilStartsWith(char *string, char *start);
int utilStricmp(char *a, char *b); int utilStricmp(char *a, char *b);
char *utilStrndup( const char *s1, size_t n); char *utilStrndup( const char *s1, size_t n);
void utilTrace(char *fmt, ...); void utilTrace(char *fmt, ...);