Skip to content

Conversation

@malucard
Copy link
Contributor

@malucard malucard commented Nov 13, 2025

fmt::localtime was removed in favor of std::localtime, so I had to change it to that to be able to build the emulator

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Walkthrough

The pull request replaces two instances of fmt::localtime(version.timestamp) with *std::localtime(&version.timestamp) across two source files. This changes the timestamp conversion mechanism from fmt's localtime wrapper to the standard library's localtime function, addressing compatibility with fmt 12.x where the fmt::localtime API was removed.

Changes

Cohort / File(s) Summary
Timestamp conversion refactoring
src/gui/gui.cc, src/main/main.cc
Replaces fmt::localtime() calls with *std::localtime() for converting version timestamps to std::tm structures in the About dialog and JSON version output.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

  • Mechanical replacement of deprecated function calls with standard library equivalents
  • No logic changes, control flow modifications, or error handling alterations
  • Changes applied consistently across two files with identical pattern

Possibly related issues

Suggested reviewers

  • nicolasnoble

Poem

🐰 A timestamp once wrapped in fmt's gentle care,
Now wears std's cloak with equal flair—
From deprecated halls to stdlib's embrace,
The rabbit refactors with style and grace! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'fmt has broken the build again' is somewhat vague and doesn't clearly describe the specific solution being implemented (replacing fmt::localtime with std::localtime). It references a problem rather than the main change. Consider a more descriptive title like 'Replace fmt::localtime with std::localtime' to clearly communicate the actual change being made.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description accurately explains the changes: fmt::localtime was removed, requiring replacement with std::localtime to restore the build.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/gui/gui.cc (2)

416-427: Critical: Potential null pointer dereference (2 instances).

Both uses of std::localtime at lines 421 and 425 can return nullptr, which would crash the application when dereferenced. This affects the "Copy to clipboard" feature in the About dialog.

Apply this diff to add null safety:

                 if (version.failed()) {
                     ImGui::EndDisabled();
                     ImGui::TextUnformatted(_("No version information.\n\nProbably built from source."));
                 } else {
+                    auto* tm = std::localtime(&version.timestamp);
+                    if (!tm) {
+                        ImGui::TextUnformatted(_("Error: Failed to convert timestamp."));
+                        ImGui::EndTabItem();
+                        return changed;
+                    }
                     if (ImGui::Button(_("Copy to clipboard"))) {
                         if (version.buildId.has_value()) {
                             clip::set_text(
                                 fmt::format("Version: {}\nBuild: {}\nChangeset: {}\nDate & time: {:%Y-%m-%d %H:%M:%S}",
                                             version.version, version.buildId.value(), version.changeset,
-                                            *std::localtime(&version.timestamp)));
+                                            *tm));
                         } else {
                             clip::set_text(fmt::format("Version: {}\nChangeset: {}\nDate & time: {:%Y-%m-%d %H:%M:%S}",
                                                        version.version, version.changeset,
-                                                       *std::localtime(&version.timestamp)));
+                                                       *tm));
                         }
                     }

437-439: Critical: Potential null pointer dereference.

Line 437 dereferences the result of std::localtime without checking for nullptr, which can crash the application when displaying the timestamp in the About dialog.

Apply this diff to add null safety:

                     ImGui::SameLine();
                     if (ImGui::SmallButton(version.changeset.c_str())) {
                         openUrl(fmt::format("https://github.com/grumpycoders/pcsx-redux/commit/{}", version.changeset));
                     }
-                    std::tm tm = *std::localtime(&version.timestamp);
+                    auto* tmPtr = std::localtime(&version.timestamp);
+                    if (!tmPtr) {
+                        ImGui::TextUnformatted(_("Date & time: Error converting timestamp"));
+                        ImGui::EndTabItem();
+                        return changed;
+                    }
+                    std::tm tm = *tmPtr;
                     std::string timestamp = fmt::format("{:%Y-%m-%d %H:%M:%S}", tm);
                     ImGui::Text(_("Date & time: %s"), timestamp.c_str());
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e90d74d and 3ecd98e.

📒 Files selected for processing (2)
  • src/gui/gui.cc (2 hunks)
  • src/main/main.cc (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: pcsx-redux (aarch64-linux)
  • GitHub Check: pcsx-redux (x86_64-linux)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: coverage
  • GitHub Check: cross-arm64
  • GitHub Check: toolchain
  • GitHub Check: macos-build-and-test-toolchain
  • GitHub Check: aur-build
  • GitHub Check: asan
  • GitHub Check: build

Comment on lines 218 to 222
fmt::print(
"{{\n \"version\": \"{}\",\n \"changeset\": \"{}\",\n \"timestamp\": \"{}\",\n \"timestampDecoded\": "
"\"{:%Y-%m-%d %H:%M:%S}\"\n}}\n",
version.version, version.changeset, version.timestamp, fmt::localtime(version.timestamp));
version.version, version.changeset, version.timestamp, *std::localtime(&version.timestamp));
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Potential null pointer dereference.

std::localtime can return nullptr if the timestamp is invalid or a system error occurs. Dereferencing without a null check will cause undefined behavior and likely crash the application.

Consider adding a null check or using a safer alternative:

+        auto* tm = std::localtime(&version.timestamp);
+        if (!tm) {
+            fmt::print("Failed to convert timestamp\n");
+            return 1;
+        }
         fmt::print(
             "{{\n  \"version\": \"{}\",\n  \"changeset\": \"{}\",\n  \"timestamp\": \"{}\",\n  \"timestampDecoded\": "
             "\"{:%Y-%m-%d %H:%M:%S}\"\n}}\n",
-            version.version, version.changeset, version.timestamp, *std::localtime(&version.timestamp));
+            version.version, version.changeset, version.timestamp, *tm);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fmt::print(
"{{\n \"version\": \"{}\",\n \"changeset\": \"{}\",\n \"timestamp\": \"{}\",\n \"timestampDecoded\": "
"\"{:%Y-%m-%d %H:%M:%S}\"\n}}\n",
version.version, version.changeset, version.timestamp, fmt::localtime(version.timestamp));
version.version, version.changeset, version.timestamp, *std::localtime(&version.timestamp));
return 0;
auto* tm = std::localtime(&version.timestamp);
if (!tm) {
fmt::print("Failed to convert timestamp\n");
return 1;
}
fmt::print(
"{{\n \"version\": \"{}\",\n \"changeset\": \"{}\",\n \"timestamp\": \"{}\",\n \"timestampDecoded\": "
"\"{:%Y-%m-%d %H:%M:%S}\"\n}}\n",
version.version, version.changeset, version.timestamp, *tm);
return 0;
🤖 Prompt for AI Agents
In src/main/main.cc around lines 218-222, the code dereferences the pointer
returned by std::localtime without checking for nullptr which can crash if
std::localtime fails; update the code to call std::localtime (or the thread-safe
localtime_r/localtime_s variant) into a std::tm pointer, check that the pointer
is not null before using it, and if it is null produce a safe fallback (e.g.,
log/print an "invalid timestamp" string or the raw integer timestamp) so the
fmt::print call never dereferences a null pointer.

@nicolasnoble
Copy link
Member

Right, bit of an overlap with #1973, but this one is a tad more simple. I'll take it but then I'll probably change it more to what #1973 does after upgrading it.

@nicolasnoble nicolasnoble merged commit fd9959a into grumpycoders:main Nov 15, 2025
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants