Skip to content

fix: avoid cctype UB, dedupe msvc-runtime errors, use std::any_of - #203

Closed
Wael-MA wants to merge 3 commits into
build-cpp:mainfrom
Wael-MA:main
Closed

fix: avoid cctype UB, dedupe msvc-runtime errors, use std::any_of#203
Wael-MA wants to merge 3 commits into
build-cpp:mainfrom
Wael-MA:main

Conversation

@Wael-MA

Copy link
Copy Markdown

Summary

Three small, behavior-preserving cleanups across the parser/generator:

  1. Avoid UB from <cctype> calls on signed charstd::isdigit, std::isupper, std::isxdigit, std::isalnum, and std::isspace were being passed raw chars, which is undefined behavior for negative (non-ASCII) bytes. Cast to unsigned char at each call site and include <cctype> explicitly in cmake_generator.cpp.

  2. De-duplicate the msvc-runtime error builder — the same "Unknown runtime..." message was built in two places; extracted into a shared msvc_runtime_error() helper that also avoids per-iteration std::string allocations (const char * loop).

  3. Replace manual scan loops with std::any_ofcontains_language_source and has_include now use the standard algorithm, which reads the intent directly and short-circuits identically.

Testing

  • cmake -B build + cmake --build passes cleanly (C++11 target).

Comment threadsrc/cmake_generator.cpp Outdated
#include "fs.hpp"
#include "project_parser.hpp"
#include <algorithm>
#include <cctype> // Wael-MA: we call isspace below, better to include it explicitly

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The comments need to go.

Comment threadsrc/cmake_generator.cpp Outdated
return false;
// Wael-MA: swapped the manual scan for std::any_of, behavior is the same
return std::any_of(sources.begin(), sources.end(), [&project_extensions](const std::string &source) {
return project_extensions.count(fs::path(source).extension().string()) > 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think this is any easier to read and std::any_of has horrible codegen in debug mode, don't think it's worthwhile.

Comment threadsrc/cmake_generator.cpp Outdated
// Wael-MA: std::any_of does the same scan, just a lot easier to read
using value_type = std::pair<std::string, std::vector<std::string>>;
return std::any_of(includes.begin(), includes.end(),
[](const value_type &itr) { return !itr.second.empty(); });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same comment as above, I don't think this makes the code any easier to read.

Comment threadsrc/cmake_generator.cpp Outdated
// Make sure the file ends in a single newline
while (!generated_cmake.empty() && std::isspace(generated_cmake.back())) {
// Wael-MA: isspace must receive an unsigned char, plain chars can be negative
while (!generated_cmake.empty() && std::isspace(static_cast<unsigned char>(generated_cmake.back()))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just use a C cast

Comment threadsrc/project_parser.cpp Outdated
@@ -657,7 +664,9 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p

auto is_cmake_arg = [](const std::string &s) {
for (auto c : s) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Change this to unsigned char c : s and then you don't have to touch the code below

Comment threadsrc/project_parser.cpp Outdated
@@ -695,7 +704,8 @@ Project::Project(const Project *parent, const std::string &path, bool build) : p
throw_key_error("Empty hash value", argItr.first, argItr.second);
}
for (char c : value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same as above

Comment threadsrc/project_parser.cpp Outdated
@@ -1308,7 +1312,9 @@ bool Project::cmake_minimum_version(int major, int minor) const {

bool Project::is_condition_name(const std::string &name) {
for (auto ch : name) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same

@Wael-MA

Copy link
Copy Markdown
Author

Hey mrexodia, I've done the changes you told me to. And removed all "// Wael-MA:" comments. Hope you approve.

@mrexodia

Copy link
Copy Markdown
Contributor

The CI is failing and it needs clang-format, but otherwise mostly good.

@Wael-MA
Wael-MA requested a review from mrexodiaAugust 16, 2026 10:52
@Wael-MA

Copy link
Copy Markdown
Author

Done, no conflicts with base branch now

@mrexodia

Copy link
Copy Markdown
Contributor

Sorry this is not reviewable, I will redo it myself in a simpler way.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Wael-MA@mrexodia