X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/96390064bbb73824660d22f972009e7ef7fbf6fa..HEAD:/src/libupkg.c diff --git a/src/libupkg.c b/src/libupkg.c index acbf80f..60dcab0 100644 --- a/src/libupkg.c +++ b/src/libupkg.c @@ -1,21 +1,22 @@ /* - * upkg: tool for manipulating Unreal Tournament packages. - * Copyright © 2009-2011 Nick Bowler + * upkg: tool for manipulating Unreal Tournament packages. + * Copyright © 2009-2012, 2022 Nick Bowler * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ +#include #include #include #include @@ -25,6 +26,16 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define UPKG_HDR_OFFSET_VERSION 4 +#define UPKG_HDR_OFFSET_LICENSE 6 +#define UPKG_HDR_OFFSET_FLAGS 8 +#define UPKG_HDR_OFFSET_NAME_COUNT 12 +#define UPKG_HDR_OFFSET_NAME_OFFSET 16 +#define UPKG_HDR_OFFSET_EXPORT_COUNT 20 +#define UPKG_HDR_OFFSET_EXPORT_OFFSET 24 +#define UPKG_HDR_OFFSET_IMPORT_COUNT 28 +#define UPKG_HDR_OFFSET_IMPORT_OFFSET 32 + /* * Print a message and execute some statement(s) if the expression evaluates * to zero. Intended to help verify that assumed constraints on the file @@ -46,7 +57,7 @@ struct upkg_name { struct upkg_export_priv { struct upkg_export pub; - long class, super; + long super; unsigned long size, offset; }; @@ -131,28 +142,23 @@ size_t upkg_decode_index(long *val, const unsigned char *bytes, size_t n) return 0; } -static struct upkg_priv *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE]) +static struct upkg_priv *init_upkg(const unsigned char *hdr) { - struct upkg_priv *pkg; + struct upkg_priv *pkg, tmp = {0}; + + tmp.pub.version = unpack_16_le(hdr+UPKG_HDR_OFFSET_VERSION); + tmp.pub.license = unpack_16_le(hdr+UPKG_HDR_OFFSET_LICENSE); + tmp.pub.flags = unpack_32_le(hdr+UPKG_HDR_OFFSET_FLAGS); + tmp.pub.name_count = unpack_32_le(hdr+UPKG_HDR_OFFSET_NAME_COUNT); + tmp.pub.export_count = unpack_32_le(hdr+UPKG_HDR_OFFSET_EXPORT_COUNT); + tmp.pub.import_count = unpack_32_le(hdr+UPKG_HDR_OFFSET_IMPORT_COUNT); + tmp.name_offset = unpack_32_le(hdr+UPKG_HDR_OFFSET_NAME_OFFSET); + tmp.export_offset = unpack_32_le(hdr+UPKG_HDR_OFFSET_EXPORT_OFFSET); + tmp.import_offset = unpack_32_le(hdr+UPKG_HDR_OFFSET_IMPORT_OFFSET); pkg = malloc(sizeof *pkg); - if (!pkg) - return NULL; - - *pkg = (struct upkg_priv) { - .pub = { - .version = unpack_16_le(hdr+4), - .license = unpack_16_le(hdr+6), - .flags = unpack_32_le(hdr+8), - .name_count = unpack_32_le(hdr+12), - .export_count = unpack_32_le(hdr+20), - .import_count = unpack_32_le(hdr+28), - }, - - .name_offset = unpack_32_le(hdr+16), - .export_offset = unpack_32_le(hdr+24), - .import_offset = unpack_32_le(hdr+32), - }; + if (pkg) + *pkg = tmp; return pkg; } @@ -271,7 +277,6 @@ static int pkg_init_exports(struct upkg_priv *pkg) while (index < pkg->pub.export_count) { struct upkg_export_priv *export = &pkg->exports[index]; - unsigned long parent_index; long tmp; /* Read some data into buffer. */ @@ -283,7 +288,7 @@ static int pkg_init_exports(struct upkg_priv *pkg) } len = 0; - rc = upkg_decode_index(&export->class, buf+len, nbuf-len); + rc = upkg_decode_index(&export->pub.class, buf+len, nbuf-len); if (rc == 0) goto err; len += rc; @@ -292,15 +297,17 @@ static int pkg_init_exports(struct upkg_priv *pkg) len += rc; if (nbuf-len < 4) goto err; - parent_index = unpack_32_le(buf+len); + tmp = unpack_s32_le(buf+len); + if (tmp < 0) + goto err; len += 4; export->pub.parent = NULL; - if (parent_index > 0) { - parent_index--; - if (parent_index >= pkg->pub.export_count) + if (tmp > 0) { + tmp--; + if (tmp >= pkg->pub.export_count) goto err; - export->pub.parent = &pkg->exports[parent_index].pub; + export->pub.parent = &pkg->exports[tmp].pub; } rc = upkg_decode_index(&tmp, buf+len, nbuf-len); @@ -532,47 +539,13 @@ const struct upkg_export *upkg_get_export(struct upkg *pub, unsigned long idx) return NULL; } -const char *upkg_export_class(struct upkg *pub, unsigned long idx, - const char **package) +const struct upkg_import *upkg_get_import(struct upkg *pub, unsigned long idx) { struct upkg_priv *pkg = (struct upkg_priv *)pub; - const struct upkg_import *iclass, *ipackage; - struct upkg_export_priv *export; - unsigned long pkg_idx; - - if (idx >= pkg->pub.export_count) - return NULL; - - export = &pkg->exports[idx]; - /* Assumption: class references are always imports. */ - format_assert(export->class <= 0, return NULL); - - /* Get the class. */ - if (export->class == 0) { - if (package) *package = "Core"; - return "Class"; - } - - pkg_idx = -(export->class + 1); - if (pkg_idx >= pkg->pub.import_count) - return NULL; - iclass = &pkg->imports[pkg_idx]; - - /* Assumption: class references are always Core.Class. */ - format_assert(!strcmp(iclass->class_package, "Core"), return NULL); - format_assert(!strcmp(iclass->class_name, "Class"), return NULL); - - ipackage = iclass->parent; - if (!ipackage) - return NULL; - - /* Assumption: package references are always Core.Package. */ - format_assert(!strcmp(ipackage->class_package, "Core"), return NULL); - format_assert(!strcmp(ipackage->class_name, "Package"), return NULL); - - if (package) *package = ipackage->name; - return iclass->name; + if (idx < pkg->pub.import_count) + return &pkg->imports[idx]; + return NULL; } struct upkg_file *upkg_export_open(struct upkg *pub, unsigned long idx)