Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix temperature readings on Intel CPUs with heterogeneous core design #1269

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions linux/LibSensors.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,43 @@ void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int existingCPUs, uns
goto out;
}

/* Read sysfs to get HT/SMT cores and correctly distribute the temperature values */
if (coreTempCount < activeCPUs) {
double oldData[existingCPUs + 1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable length array is not recommended in C.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid VLA. Although they are part of C99 (which htop targets), there are later language versions that make them optional. Also, having dynamically sized data on the stack is an accident waiting to happen, from a security PoV. Thus: No VLAs!

Copy link
Author

@dawidpotocki dawidpotocki Jul 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for a late response, but isn't this also a VLA?

double data[existingCPUs + 1];

That's where I got this from.

I don't mind changing it though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LibSensors code is not the cleanest in some places … ;-)

That said, I did some cleanup in #1273.

memcpy(oldData, data, sizeof(oldData));

int dataCell = 1;
for (unsigned int i = 0; i < existingCPUs; i++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use size_t for things that represent the number of items/counts of things.

char path[100];
sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have xSnprintf function in htop codebase. Please use that instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if you are iterating over several items in a common parent directory, it might be worth using things like opendir and openat.

FILE* file = fopen(path, "r");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fopen APIs are usually avoided due to their overhead and performance impact. As mentioned above, use opendir and openat (cf. wrappers in XUtils.h) instead.

if (file == NULL) {
data[i+1] = NAN;
dataCell++;
continue;
}

char contents[10];
fgets(contents, 10, file);
fclose(file);

int start, end;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use some sane initialization, even though sscanf will potentially assign those variables.

int rangeNums = sscanf(contents, "%d-%d", &start, &end);
Comment on lines +280 to +285
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This buffer is too short for the potential values that could be returned by the kernel. Should be at least 24 bytes (2x 10 bytes for int32_t plus 2 bytes for - and \n, plus one final \0 terminator.

Comment on lines +284 to +285
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer fixed width integer types and suffixes defined in inttypes.h.


if (rangeNums == 1) {
data[i+1] = oldData[dataCell];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent use of indexing source. When just one value given, this should equal to running the below code for just the start index, which is not the case at all.

dataCell++;
} else if (rangeNums == 2) {
for (int j = start; j <= end; j++) {
data[j+1] = oldData[dataCell];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unchecked buffer overflow from untrusted/unsanitized input.

i++;
}
dataCell++;
i--;
}
}
}

out:
for (unsigned int i = 0; i <= existingCPUs; i++)
cpus[i].temperature = data[i];
Expand Down