Skip to content

Commit

Permalink
[manape] Reworked the parsing of VersionInfo string tables which was …
Browse files Browse the repository at this point in the history
…erroneous when they contained padding.

[plot_timestamps] Prevented an exception when trying to plot empty data. The -i parameter is now handled properly.
  • Loading branch information
JusticeRage committed May 6, 2020
1 parent 8a54655 commit b2600d2
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 49 deletions.
9 changes: 5 additions & 4 deletions bin/plot_timestamps.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def validate_args():
parser.add_argument('--no-color', action='store_true', help='Disables color in the graphs')
# The rationale for this is that we want to exclude samples which have an obvious fake compilation date, as well
# as those that have a default timestamp set in the nineties.
parser.add_argument('--ignore-older-than', '-i', default=10,
parser.add_argument('--ignore-older-than', '-i', default=10, type=int,
help="Ignore samples that are more than N years old. (Default: 10)")
parser.add_argument('--rebase-timezone', '-t',
help="Translates all the timestamps to the desired timezone. (Ex: 'UTC+2', 'UTC-6'...)")
Expand Down Expand Up @@ -262,11 +262,12 @@ def main():

# Print the charts.
print("\n###############################################################################")
if "day" in args.charts:
# The any() condition verifies that the input contains data to plot.
if "day" in args.charts and any(x for x in r.activity_hourly.values()):
print_charts(r.activity_hourly, "Distribution of timestamps over the day", args)
if "week" in args.charts:
if "week" in args.charts and any(x for x in r.activity_weekly.values()):
print_charts(r.activity_weekly, "Distribution of timestamps over the week", args, weekday=True)
if "year" in args.charts:
if "year" in args.charts and any(x for x in r.activity_yearly.values()):
print_charts(r.activity_yearly, "Distribution of timestamps over the years", args)


Expand Down
65 changes: 20 additions & 45 deletions manape/resources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,6 @@ DECLSPEC pversion_info Resource::interpret_as()
auto res = boost::make_shared<version_info>();
unsigned int bytes_read; // Is calculated by calling ftell before and after reading a structure, and keeping the difference.
unsigned int bytes_remaining;
unsigned int padding;
unsigned int language;
std::stringstream ss;

Expand Down Expand Up @@ -564,63 +563,39 @@ DECLSPEC pversion_info Resource::interpret_as()
// Read the StringTable
while (bytes_remaining > 0)
{
bytes_read = ftell(f);
unsigned int current_offset = ftell(f);
if (!parse_version_info_header(*current_structure, f))
{
res.reset();
goto END;
}

// Ignore empty entries
if (current_structure->ValueLength == 0)
// Structures are aligned on DWORD boundaries, but the Length field doesn't reflect that. Update
// it here to facilitate the parsing.
if (current_structure->Length % 4 != 0) {
current_structure->Length += 4 - current_structure->Length % 4;
}

// Only process structures that contain data.
if (current_structure->ValueLength != 0)
{
padding = 16 - ftell(f) % 16;
if (padding != 16) {
fseek(f, padding, SEEK_CUR); // Realign on a 16-byte boundray. I'm not 100% sure it's what's needed here.
}
bytes_read = ftell(f) - bytes_read;
if (bytes_read < bytes_remaining) { // Padding in the last entry isn't included in the length.
bytes_remaining -= bytes_read;
}
else {
bytes_remaining = 0;
std::string value;
if (ftell(f) - current_offset < current_structure->Length) {
value = utils::read_unicode_string(f);
}
continue;
// Add the key/value to our internal representation
auto p = boost::make_shared<string_pair>(current_structure->Key, value);
res->StringTable.push_back(p);
}

std::string value;
// If the string is null, there won't even be a null terminator.
if (ftell(f) - bytes_read < current_structure->Length) {
value = utils::read_unicode_string(f);
}
bytes_read = ftell(f) - bytes_read;
if (bytes_remaining < bytes_read)
if (current_structure->Length < bytes_remaining)
{
bytes_remaining = 0;
PRINT_WARNING << bytes_read - bytes_remaining << " excess bytes have been read from a StringFileInfo!"
<< DEBUG_INFO << std::endl;
bytes_remaining -= current_structure->Length;
unsigned int next_structure_offset = current_offset + current_structure->Length;
fseek(f, next_structure_offset, SEEK_SET);
}
else {
bytes_remaining -= bytes_read;
}

// Add the key/value to our internal representation
auto p = boost::make_shared<string_pair>(current_structure->Key, value);
res->StringTable.push_back(p);

// The next structure is 4-byte aligned.
padding = ftell(f) % 4;
if (padding)
{
fseek(f, padding, SEEK_CUR);
// The last padding doesn't seem to be included in the length given by the structure.
// So if there are no more remaining bytes, don't stop here. (Otherwise, integer underflow.)
if (padding < bytes_remaining) {
bytes_remaining -= padding;
}
else {
bytes_remaining = 0;
}
bytes_remaining = 0;
}
}

Expand Down

0 comments on commit b2600d2

Please sign in to comment.