In xpszip.c there is an error in xps_find_part() (line 160). xps_find_part() uses a function xps_strcasecmp(), but xps_strcasecmp() will always return zero (a match) if the first string is shorter than the second string, which means that a lot of matches will be incorrect if xps_strcasecmp() is expected to behave as strcasecmp() would. I'm not sure about all events that would trigger this, but in my particular case it was not deobfuscating fonts. The xps_new_glyph() function was calling xps_find_part(), but xps_find_part() was always returning the first "part" of the context because the first part's name was shorter than font part's name. By changing "xps_strcasecmp()" to "strcasecmp()" in xpszip.c:xps_find_part(), obfuscated fonts become deobfuscated and loaded correctly.
Created attachment 4246 [details] Patch for xps_strcasecmp() issue Patch using -p1 and inside xps directory.
Upon further investigation, I've found that xps_strcasecmp() returns a match when string1 is shorter than string2 only when the case is different! After reviewing the code for xps_strcasecmp() I found it uses another compatibility function xps_tolower(). The logic in xps_tolower() is the problem. Line 7 of xpsmem.c: if (x >= 'A' || x <= 'Z') should read if (x >= 'A' && x <= 'Z') The attached patch is therefore not an ideal solution considering strcasecmp is not available on all platforms.
This bug was discovered and fixed a long time ago. You may want to update to a newer version of the source.
Sorry to bring up an old bug. I will use a snapshot rather than the 1.52 source.