Skip to content

Adding back private implementation of printf #3026

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

Merged
merged 5 commits into from
Oct 3, 2024
Merged

Conversation

josesimoes
Copy link
Member

@josesimoes josesimoes commented Sep 30, 2024

Description

Motivation and Context

  • Remains as the best suited implementation of printf.
  • The library author kindly reviewed this code and pointed out that we were already using the latest (v1.3) of the library. The changes that were added along with the original code (see Replace nanoprintf with es-printf #2662) allowed to tackle the issues with large doubles and floating point precision.

How Has This Been Tested?

  • Unit tests from mscorlib.

Screenshots

Types of changes

  • Improvement (non-breaking change that improves a feature, code or algorithm)
  • Bug fix (non-breaking change which fixes an issue with code or algorithm)
  • New feature (non-breaking change which adds functionality to code)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Config and build (change in the configuration and build system, has no impact on code or features)
  • Dev Containers (changes related with Dev Containers, has no impact on code or features)
  • Dependencies/declarations (update dependencies or assembly declarations and changes associated, has no impact on code or features)
  • Documentation (changes or updates in the documentation, has no impact on code or features)

Checklist

  • My code follows the code style of this project (only if there are changes in source code).
  • My changes require an update to the documentation (there are changes that require the docs website to be updated).
  • I have updated the documentation accordingly (the changes require an update on the docs in this repo).
  • I have read the CONTRIBUTING document.
  • I have tested everything locally and all new and existing tests passed (only if there are changes in source code).

Summary by CodeRabbit

  • New Features

    • Introduced nanoprintf functionality for enhanced string formatting, including support for various data types and floating-point numbers.
    • Added new functions for safe string formatting (snprintf_, vsnprintf_) and improved handling of numeric formatting.
    • Enhanced OpenThread CLI interactions and device management on the ESP32 platform.
    • Implemented robust string manipulation functions with safety checks across various platforms.
    • Added floating-point formatting capabilities in multiple target environments.
  • Bug Fixes

    • Improved logic for buffer handling and string manipulations to prevent overflows and ensure safe operations.
  • Documentation

    • Updated header files to include new functionalities and configuration options for formatted output.

Copy link

coderabbitai bot commented Sep 30, 2024

Walkthrough

The changes introduce the nanoprintf library into the project, enhancing string formatting capabilities for various data types, including integers and floating-point numbers. Modifications include the addition of new header and source files, updates to project configurations, and conditional inclusions based on compilation settings. The changes also refine existing formatting methods and string manipulation functions across multiple files, ensuring better handling of precision and formatting requirements.

Changes

File(s) Change Summary
CMake/Modules/FindNF_CoreCLR.cmake, src/CLR/CorLib/CorLib.vcxproj, src/CLR/Core/Core.vcxproj, src/CLR/Core/Core.vcxproj.filters, src/CLR/Diagnostics/Diagnostics.vcxproj Added new include directory and source file for nanoprintf, updated project configurations to include nanoprintf paths for various build configurations.
src/CLR/CorLib/CorLib.h, src/CLR/Diagnostics/Diagnostics.h Introduced conditional compilation for including <nanoprintf.h> based on the VIRTUAL_DEVICE macro.
src/CLR/CorLib/corlib_native_System_Number.cpp Enhanced numeric formatting capabilities by updating methods to utilize nanoprintf, improving precision and format handling for various numeric types.
src/CLR/Helpers/nanoprintf/nanoprintf.c, src/CLR/Helpers/nanoprintf/nanoprintf.h Implemented lightweight printf-like functionality, including new formatting functions and macros tailored for embedded systems.
targets/AzureRTOS/_common/nanoCLR/nanoCRT.cpp, targets/ChibiOS/_nanoCLR/nanoCRT.cpp, targets/ESP32/_nanoCLR/nanoCRT.cpp, targets/FreeRTOS/_common/nanoCLR/nanoCRT.cpp, targets/TI_SimpleLink/_nanoCLR/nanoCRT.cpp Added functions for formatting floating-point numbers and enhanced string manipulation functions, including safety checks and new debug printing capabilities.
src/CLR/Diagnostics/Info_Safeprintf.cpp Modified the CLR_SafeSprintfV function to improve handling of return values and buffer overflow conditions.

Possibly related PRs

Suggested labels

Type: dependencies, Area: Config-and-Build

Suggested reviewers

  • Ellerbach

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@josesimoes josesimoes added the Area: Common libs Everything related with common libraries label Sep 30, 2024
Copy link

@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: 6

🧹 Outside diff range and nitpick comments (41)
src/CLR/Diagnostics/Diagnostics.h (1)

Line range hint 7-13: Consider removing commented-out includes if no longer needed.

There are several commented-out include statements in this file:

// #include <nanoCLR_Diagnostics.h>
// #include <nanoCLR_Graphics.h>
// #include <nanoCLR_Hardware.h>
// #include <core.h>
// #include <spot_net_native.h>

If these includes are no longer needed, it would be best to remove them entirely rather than leaving them commented out. This helps maintain cleaner and more maintainable code. If they are still needed but currently disabled for a specific reason, please add a comment explaining why they are commented out and under what circumstances they might be needed in the future.

Also applies to: 17-17

src/CLR/Diagnostics/Info_Safeprintf.cpp (1)

Line range hint 20-24: LGTM: Overall changes are well-implemented

The modifications to CLR_SafeSprintfV are well-implemented and improve its robustness. The unchanged parts, including buffer null-termination and pointer/size updates, remain correct and consistent with the changes.

Minor optimization suggestion: Consider combining the buffer update operations into a single statement for slightly improved readability:

iBuffer -= (szBuffer += chars)[0] = 0;

This change is optional and doesn't affect functionality.

The CLR_SafeSprintf function remains unchanged and correct.

Also applies to: 26-41

src/CLR/Core/Core.vcxproj.filters (1)

135-137: LGTM! Consider grouping related files together.

The addition of nanoprintf.c to the project is correct and aligns with the PR objectives. The file is appropriately placed in the "Source Files" filter.

For better organization, consider grouping related files together. You might want to move this entry next to other string or formatting-related source files if they exist in the project.

src/CLR/CorLib/CorLib.vcxproj (2)

155-155: Please clarify the rationale for using a private printf implementation.

The addition of the nanoprintf library aligns with the PR objective of "Adding back private implementation of printf". While this approach can offer benefits such as increased control, potential performance improvements, and customization options, it's important to consider the long-term implications:

  1. Maintenance: How will the project ensure the private implementation stays up-to-date and bug-free?
  2. Compatibility: Are there any known deviations from standard printf behavior that developers should be aware of?
  3. Performance: Has the team conducted benchmarks to confirm performance improvements over the previous implementation?

Could you please provide more context on why this private implementation is preferred over standard library options?

Also applies to: 168-168, 183-183, 200-200


211-211: Minor: Newline character removed at end of file.

The newline character at the end of the file has been removed. While this doesn't affect functionality, it's worth noting that some coding standards recommend keeping a newline at the end of files. Consider checking your project's style guide for any specific requirements.

Overall, the changes in this file are minimal and focused on integrating the nanoprintf library. The consistency across different build configurations is commendable, and the changes align well with the stated PR objectives.

targets/ChibiOS/_nanoCLR/nanoCRT.cpp (7)

Line range hint 15-42: Leverage nanoprintf for floating-point formatting in hal_snprintf_float

The hal_snprintf_float function implements custom floating-point formatting logic. Since the nanoprintf library supports floating-point formatting, consider utilizing npf_snprintf to simplify the code and maintain consistency.

Refactor the function to use npf_snprintf from the nanoprintf library:

-int hal_snprintf_float(char *buffer, size_t len, const char *format, int32_t f)
-{
-    // Custom implementation
-}
+int hal_snprintf_float(char *buffer, size_t len, const char *format, float f)
+{
+    return npf_snprintf(buffer, len, format, f);
+}

Line range hint 44-73: Simplify hal_snprintf_double by using nanoprintf

The hal_snprintf_double function manually handles double formatting. To reduce complexity and potential errors, consider using npf_snprintf from the nanoprintf library, which already provides robust support for double formatting.

Modify the function as follows:

-int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t &d)
-{
-    // Custom implementation
-}
+int hal_snprintf_double(char *buffer, size_t len, const char *format, double d)
+{
+    return npf_snprintf(buffer, len, format, d);
+}

Line range hint 83-94: Ensure buffer safety in debug_printf

The debug_printf function uses a fixed-size buffer char buffer[256]; without ensuring the formatted output fits within the buffer, risking a buffer overflow.

Implement a check to ensure the formatted string does not exceed the buffer size. You can adjust the vsnprintf call and handle cases where the output is truncated:

-    int len = vsnprintf(buffer, sizeof(buffer) - 1, format, arg_ptr);
+    int len = vsnprintf(buffer, sizeof(buffer), format, arg_ptr);
+    if (len < 0)
+    {
+        // Handle encoding errors
+        len = 0;
+    }
+    else if ((size_t)len >= sizeof(buffer))
+    {
+        // Output was truncated to fit the buffer
+        len = sizeof(buffer) - 1;
+    }
+    buffer[len] = '\0'; // Ensure null termination

Line range hint 96-117: Use safer string copying in hal_strcpy_s

The use of strcpy poses a risk of buffer overflows despite prior size checks. Employ strncpy or ensure that the destination buffer is adequately handled to prevent potential security issues.

Update the function to use strncpy and guarantee null termination:

-    strcpy(strDst, strSrc);
+    strncpy(strDst, strSrc, sizeInBytes - 1);
+    strDst[sizeInBytes - 1] = '\0'; // Ensure null termination

Line range hint 119-141: Prevent potential out-of-bounds write in hal_strncpy_s

Assigning strDst[count] = 0; may result in writing beyond the buffer if count equals or exceeds sizeInBytes.

Modify the function to include a check and adjust the null termination accordingly:

     if (sizeInBytes < count + 1)
     {
         _ASSERTE(FALSE);
         strDst[0] = 0;
         return 1;
     }

-    strDst[count] = 0;
     strncpy(strDst, strSrc, count);
+    strDst[count] = 0; // Ensure null termination within bounds
     return 0;

Line range hint 143-152: Add null pointer check in hal_strlen_s

The function hal_strlen_s does not check if str is NULL before dereferencing it, which can lead to undefined behavior.

Include a null pointer check at the beginning of the function:

+    if (str == NULL)
+    {
+        _ASSERTE(FALSE);
+        return 0;
+    }

Line range hint 154-166: Clarify return values in hal_strncmp_s for invalid inputs

Currently, when either str1 or str2 is NULL, the function returns 1, which could be confused with a valid comparison result.

Return a distinct error code to indicate invalid input parameters:

     if (str1 == NULL || str2 == NULL)
     {
         _ASSERTE(FALSE);
-        return 1;
+        return INT_MAX; // Return a distinct error code
     }
targets/FreeRTOS/_common/nanoCLR/nanoCRT.cpp (6)

Line range hint 25-55: Refactor duplicate logic in hal_snprintf_float and hal_snprintf_double

The functions hal_snprintf_float and hal_snprintf_double share similar logic for formatting numbers. Consider refactoring the common code into a helper function to reduce duplication and improve maintainability.


Line range hint 56-91: Unnecessary passing of parameter by reference in hal_snprintf_double

The parameter d in hal_snprintf_double is passed by reference (int64_t &d), but the function does not modify it. Passing by reference is unnecessary and could be misleading. Consider passing d by value to maintain consistency and clarity.

Suggested change:

-int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t &d)
+int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t d)

Line range hint 100-115: Potential buffer overrun in debug_printf

In debug_printf, vsnprintf is called with sizeof(buffer) - 1, which may prevent proper null-termination if the formatted output exactly fills the buffer. This could lead to undefined behavior when using the buffer contents.

Consider using sizeof(buffer) to ensure the buffer is correctly null-terminated. Also, verify that len does not exceed sizeof(buffer) - 1 before writing to DebuggerPort_Write.

Suggested change:

-    int len = vsnprintf(buffer, sizeof(buffer) - 1, format, arg_ptr);
+    int len = vsnprintf(buffer, sizeof(buffer), format, arg_ptr);

Line range hint 145-160: Potential out-of-bounds write in hal_strncpy_s

In hal_strncpy_s, when sizeInBytes is less than count + 1, the function writes a null terminator to strDst[0]. If sizeInBytes is zero, this could result in an out-of-bounds write. Ensure strDst has enough space before writing to it.

Suggested change:

    if (sizeInBytes < count + 1)
    {
        _ASSERTE(FALSE);
+       if (sizeInBytes > 0 && strDst != NULL)
+       {
+           strDst[0] = '\0';
+       }
        return 1;
    }

Line range hint 165-170: Missing NULL pointer check in hal_strlen_s

The function hal_strlen_s does not check if str is NULL before dereferencing it. Passing a NULL pointer will lead to undefined behavior. Add a NULL check to enhance robustness.

Suggested change:

+    if (str == NULL)
+    {
+        _ASSERTE(FALSE);
+        return 0;
+    }

Line range hint 185-200: Missing NULL pointer checks in hal_stricmp

The hal_stricmp function does not verify if dst or src are NULL before usage. Dereferencing a NULL pointer results in undefined behavior. It's recommended to add NULL checks for both dst and src.

Suggested change:

+    if (dst == NULL || src == NULL)
+    {
+        _ASSERTE(FALSE);
+        return 0;
+    }
targets/TI_SimpleLink/_nanoCLR/nanoCRT.cpp (5)

Line range hint 46-87: Avoid using C++ references in function parameters

The function hal_snprintf_double uses a C++ reference parameter int64_t &d, which may cause compatibility issues if the code is compiled as C. Since this file is intended for use in embedded systems where C is often preferred, consider passing the parameter by value or using a pointer instead.

Apply this diff to modify the function signature:

-int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t &d)
+int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t d)

Adjust the function implementation and any calls to this function accordingly.


Line range hint 127-147: Potential buffer overflow in hal_strncpy_s

In the hal_strncpy_s function, assigning strDst[count] = 0; can cause a buffer overflow if count is equal to or exceeds sizeInBytes, as it writes beyond the allocated buffer. Additionally, strncpy does not guarantee null-termination if the source string is longer than count.

Apply this diff to ensure safe copying and proper null-termination:

 int hal_strncpy_s(char *strDst, size_t sizeInBytes, const char *strSrc, size_t count)
 {
     NATIVE_PROFILE_PAL_CRT();
-#undef strncpy
     if (strDst == NULL || strSrc == NULL || sizeInBytes == 0)
     {
         _ASSERTE(FALSE);
         return 1;
     }

-    if (sizeInBytes < count + 1)
+    if (sizeInBytes <= count)
     {
         _ASSERTE(FALSE);
         strDst[0] = 0;
         return 1;
     }

-    strDst[count] = 0;
     strncpy(strDst, strSrc, count);
+    strDst[count] = 0; // Ensure null-termination
     return 0;

-#define strncpy DoNotUse_*strncpy[]
 }

Alternatively, consider using a safer string copy function that guarantees null-termination, such as strlcpy if available.


Line range hint 108-125: Unnecessary macro manipulation in hal_strcpy_s

The use of #undef strcpy and redefining it can lead to confusion and maintenance challenges. It might suppress the use of strcpy elsewhere unintentionally. Consider removing these macro manipulations and ensure that strcpy is used safely within this function.


Line range hint 152-175: Simplify error handling in hal_strncmp_s

The function uses _ASSERTE(FALSE); when encountering null pointers. Ensure that _ASSERTE is defined in your environment. If not, consider using standard assert or handle the error appropriately. Also, the macro manipulation with strncmp may be unnecessary and could be removed for clarity.


Line range hint 178-192: Refactor hal_stricmp for readability

The hal_stricmp function manually adjusts character cases for comparison. You can simplify this by using the tolower function from <ctype.h>, which enhances readability and maintainability.

Apply this diff to refactor the function:

+#include <ctype.h>

 int hal_stricmp(const char *dst, const char *src)
 {
-    int f = 0, l = 0;
+    int f, l;

     do
     {
-        if (((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z'))
-        {
-            f -= 'A' - 'a';
-        }
-        if (((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z'))
-        {
-            l -= 'A' - 'a';
-        }
+        f = tolower((unsigned char)*dst++);
+        l = tolower((unsigned char)*src++);
     } while (f && (f == l));

     return (f - l);
 }

Ensure that you include <ctype.h> at the top of the file.

targets/ESP32/_nanoCLR/nanoCRT.cpp (4)

Line range hint 29-54: Refactor hal_snprintf_float to eliminate code duplication

The hal_snprintf_float function contains similar logic in both the negative and positive number handling blocks. Consider refactoring to reduce code duplication, which will enhance maintainability and readability.

You can combine the common code and handle the sign separately:

int hal_snprintf_float(char *buffer, size_t len, const char *format, int32_t f)
{
    NATIVE_PROFILE_PAL_CRT();

    uint32_t i;
    uint32_t dec;
+   char sign = '\0';

    if (f < 0)
    {
        // negative number
        i = (uint32_t)-f;
+       sign = '-';
    }
    else
    {
        // positive number
        i = (uint32_t)f;
    }

    dec = i & ((1 << HAL_FLOAT_SHIFT) - 1);
    i = i >> HAL_FLOAT_SHIFT;

    if (dec != 0)
        dec = (dec * (uint32_t)HAL_FLOAT_PRECISION + (1 << (HAL_FLOAT_SHIFT - 1))) >> HAL_FLOAT_SHIFT;

-   if (f < 0)
-       return hal_snprintf(buffer, len, "-%d.%03u", i, (uint32_t)dec);
-   else
-       return hal_snprintf(buffer, len, "%d.%03u", i, (uint32_t)dec);
+   if (sign)
+       return hal_snprintf(buffer, len, "%c%d.%03u", sign, i, dec);
+   else
+       return hal_snprintf(buffer, len, "%d.%03u", i, dec);
}

Line range hint 55-89: Refactor hal_snprintf_double to eliminate code duplication

Similar to hal_snprintf_float, the hal_snprintf_double function has redundant code for handling negative and positive numbers. Refactoring will improve code clarity and reduce maintenance efforts.

Refactored version:

int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t &d)
{
    NATIVE_PROFILE_PAL_CRT();

    uint64_t i;
    uint32_t dec; // 32-bit is enough for decimal part
+   char sign = '\0';

    if (d < 0)
    {
        // negative number
        i = (uint64_t)-d;
+       sign = '-';
    }
    else
    {
        // positive number
        i = (uint64_t)d;
    }

    i += ((1 << (HAL_DOUBLE_SHIFT - 1)) / HAL_DOUBLE_PRECISION); // rounding increment before split

    dec = i & ((1 << HAL_DOUBLE_SHIFT) - 1);
    i = i >> HAL_DOUBLE_SHIFT;

    if (dec != 0)
        dec = (dec * HAL_DOUBLE_PRECISION + ((1 << (HAL_DOUBLE_SHIFT - 1)) % HAL_DOUBLE_PRECISION)) >>
              HAL_DOUBLE_SHIFT;

-   if (d < 0)
-       return hal_snprintf(buffer, len, "-%lld.%04u", (int64_t)i, (uint32_t)dec);
-   else
-       return hal_snprintf(buffer, len, "%lld.%04u", (int64_t)i, (uint32_t)dec);
+   if (sign)
+       return hal_snprintf(buffer, len, "%c%lld.%04u", sign, (int64_t)i, dec);
+   else
+       return hal_snprintf(buffer, len, "%lld.%04u", (int64_t)i, dec);
}

Line range hint 55-55: Consider changing the parameter from reference to value

The function hal_snprintf_double accepts int64_t &d as a parameter. Since the function does not modify d, and to maintain consistency with the rest of the codebase, consider passing d by value instead of by reference.

-int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t &d)
+int hal_snprintf_double(char *buffer, size_t len, const char *format, int64_t d)

Line range hint 29-89: Ensure unit tests cover the new formatting functions

To verify the correctness of hal_snprintf_float and hal_snprintf_double, please ensure these functions are thoroughly tested. Adequate unit tests will help catch edge cases and potential bugs related to floating-point formatting.

Do you want me to assist in writing unit tests for these functions or open a GitHub issue to track this task?

targets/AzureRTOS/_common/nanoCLR/nanoCRT.cpp (1)

Line range hint 94-98: Handle potential negative return value from vsnprintf

The vsnprintf function may return a negative value if an encoding error occurs. Using a negative len in DebuggerPort_Write can lead to undefined behavior.

Consider adding a check for negative len before proceeding:

 int len = vsnprintf(buffer, sizeof(buffer) - 1, format, arg_ptr);
+if (len < 0) {
+    va_end(arg_ptr);
+    return;
+}
 
 DebuggerPort_Write(HalSystemConfig.stdio, buffer, len, 0); // skip null terminator

This ensures that you do not attempt to write an invalid number of bytes, and the function exits gracefully on error.

targets/ESP32/_Network/NF_ESP32_OpenThread.cpp (11)

Line range hint 293-293: Use delete[] when deallocating array allocated with new[]

In the OpenThreadCliInput function, you are allocating memory using new[], but deallocating it with delete. This leads to undefined behavior. When allocating memory with new[], you must deallocate it with delete[].

Apply this diff to fix the deallocation:

-delete cliLine;
+delete[] cliLine;

Line range hint 215-215: Correct the buffer size calculation in vsnprintf to prevent buffer overflow

In the cliOutputCallback function, the buffer size passed to vsnprintf may lead to a buffer overflow. The size parameter should reflect the remaining space in the buffer starting from the current index.

Apply this diff to correct the buffer size calculation:

-vsnprintf(&cliLineBuffer[cliLineBufferCount], cliBufferSize - length, aFormat, aArguments);
+vsnprintf(&cliLineBuffer[cliLineBufferCount], cliBufferSize - cliLineBufferCount, aFormat, aArguments);

Explanation:

  • cliBufferSize - cliLineBufferCount correctly computes the remaining space in cliLineBuffer.

Line range hint 204-204: Avoid using vsnprintf with nullptr and zero size

Using vsnprintf with a nullptr destination and zero size is non-standard and may lead to undefined behavior depending on the implementation of nanoprintf. It's safer to use an alternative method to calculate the required buffer length.

Consider replacing the length calculation with a safer alternative. For example:

-int length = vsnprintf(nullptr, 0, aFormat, aArguments);
+int length = npf_vsnprintf(nullptr, 0, aFormat, aArguments);

Or, if nanoprintf does not support this usage, consider a workaround:

char tempBuffer[1];
int length = vsnprintf(tempBuffer, 0, aFormat, aArguments);

Ensure that this usage is supported by nanoprintf.


Line range hint 138-150: Add bounds checking to prevent buffer overflow in hexTobin function

The hexTobin function does not check the size of the target buffer, which may lead to a buffer overflow if the src string is longer than the target buffer can hold.

Modify the function to accept the size of the target buffer and add bounds checking. Here's a suggested refactor:

-int hexTobin(const char *src, uint8_t *target)
+int hexTobin(const char *src, uint8_t *target, size_t targetSize)
 {
     int len = 0;

     while (*src && src[1])
     {
+        if (len >= targetSize) {
+            // Prevent buffer overflow
+            break;
+        }
         *(target++) = charTobyte(*src) * 16 + charTobyte(src[1]);
         src += 2;
         len++;
     }

     return len;
 }

Remember to update all calls to hexTobin to pass the targetSize parameter.


Line range hint 278-284: Potential race condition with cliHandleResponse

Access to cliHandleResponse is not synchronized, which could lead to race conditions if OpenThreadCliInput and cliOutputCallback are called from different threads.

Consider adding synchronization mechanisms like mutexes to protect shared variables:

std::mutex cliMutex;

void OpenThreadCliInput(const char *inputLine, bool response)
{
    std::lock_guard<std::mutex> lock(cliMutex);
    // ... rest of the code ...
}

int cliOutputCallback(void *aContext, const char *aFormat, va_list aArguments)
{
    std::lock_guard<std::mutex> lock(cliMutex);
    // ... rest of the code ...
}

Ensure that all accesses to shared variables like cliHandleResponse, cliOutputsList, and cliLineBuffer are protected.


Line range hint 87-116: Improve readability of setDeviceType function with consistent indentation

The indentation within the setDeviceType function is inconsistent, which may reduce code readability.

Consider adjusting the indentation to improve readability:

 static void setDeviceType(ThreadDeviceType devType, uint32_t pollPeriod)
 {
     otInstance *instance = esp_openthread_get_instance();

     otLinkModeConfig linkMode = {linkMode.mRxOnWhenIdle = true};

     switch (devType)
     {
-        case ThreadDeviceType_Router:
+    case ThreadDeviceType_Router:
         linkMode.mRxOnWhenIdle = true;
         linkMode.mDeviceType = true;
         linkMode.mNetworkData = true;
         break;

-        case ThreadDeviceType_EndDevice:
+    case ThreadDeviceType_EndDevice:
         linkMode.mRxOnWhenIdle = true;
         // Not FTD (end device)
         linkMode.mDeviceType = false;
         linkMode.mNetworkData = false;
         break;

-        case ThreadDeviceType_SleepyEndDevice:
+    case ThreadDeviceType_SleepyEndDevice:
         // Not receiving all the time
         linkMode.mRxOnWhenIdle = false;
         linkMode.mDeviceType = false;
         linkMode.mNetworkData = false;

         // Set poll period for polling
         if (otLinkSetPollPeriod(instance, pollPeriod) != OT_ERROR_NONE)
         {
             ESP_LOGE(TAG, "Failed to set OpenThread poll period.");
         }

         powerSaveInit();
         break;
     }

     if (otThreadSetLinkMode(instance, linkMode) != OT_ERROR_NONE)
     {
         ESP_LOGE(TAG, "Failed to set OpenThread linkmode.");
     }
 }

Line range hint 215-215: Check return value of vsnprintf for errors

The vsnprintf function may return a negative value if an encoding error occurs. Not checking its return value might lead to incorrect behavior.

Consider checking the return value of vsnprintf:

-int length = vsnprintf(&cliLineBuffer[cliLineBufferCount], cliBufferSize - cliLineBufferCount, aFormat, aArguments);
+int result = vsnprintf(&cliLineBuffer[cliLineBufferCount], cliBufferSize - cliLineBufferCount, aFormat, aArguments);
+if (result < 0) {
+    // Handle error
+    return result;
+}
+// Update count
+cliLineBufferCount += result;

This ensures that encoding errors are properly handled.


Line range hint 278-293: Avoid memory leak in OpenThreadCliInput if exceptions occur

If an exception is thrown after allocating cliLine, the memory may not be deallocated.

Consider using smart pointers for automatic memory management:

-char *cliLine = new char[length + 1];
+std::unique_ptr<char[]> cliLine(new char[length + 1]);
 hal_strcpy_s(cliLine.get(), length + 1, inputLine);

 otCliInputLine(cliLine.get());

-delete[] cliLine;
+// No need to delete manually; `unique_ptr` handles it.

This ensures that memory is freed even if an exception occurs.


Line range hint 343-369: Simplify initOpenThread function by avoiding magic numbers

The function uses hardcoded numbers for error checking and configuration. Using named constants or enumerations improves readability.

Define error codes and configuration values as constants or enums:

const int EVENT_FD_MAX = 3;
const int DEFAULT_STACK_SIZE = 10000;

Update the code to use these constants.


Line range hint 87-116: Validate device type input in setDeviceType

There is no default case to handle unexpected devType values, which might lead to uninitialized linkMode configurations.

Consider adding a default case to handle invalid devType inputs:

     switch (devType)
     {
         // Existing cases...
         break;

+    default:
+        ESP_LOGE(TAG, "Invalid ThreadDeviceType value.");
+        return;
     }

Add nullptr checks for pskc and url before calling otJoinerStart.

Ensure that both pskc and url are validated to be non-null before invoking otJoinerStart to prevent potential crashes or undefined behavior.

  • File: targets/ESP32/_Network/NF_ESP32_OpenThread.cpp
  • Lines: 393-396
🔗 Analysis chain

Line range hint 393-396: Handle possible nullptr for pskc and url in JoinerStart

The otJoinerStart function may not handle nullptr values for pskc and url properly, leading to unexpected behavior or crashes.

Please verify that pskc and url are not nullptr before calling otJoinerStart, or ensure that otJoinerStart safely handles nullptr values.

Run the following script to check for nullptr handling in otJoinerStart:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if `otJoinerStart` handles `nullptr` for `pskc` and `url`.

# Using `ast-grep` to find the `otJoinerStart` function definition
ast-grep --lang c \
    --pattern $'otError otJoinerStart($_, $_, $_, $_, $_, $_, $_, $_, $_)' \
    --json

# Examine the function implementation to ensure it handles `nullptr` appropriately.

Length of output: 444


Script:

#!/bin/bash
# Description: Find all calls to `otJoinerStart` and display surrounding code to check handling of `pskc` and `url`.

rg 'otJoinerStart' -C 2

Length of output: 435

src/CLR/CorLib/corlib_native_System_Number.cpp (1)

Line range hint 89-92: Remove redundant casting in DoPrintfOnDataType for DATATYPE_I8

The double (int)(int) cast before the snprintf function appears redundant and may be a typographical error. It should be corrected to a single (int) cast for consistency and correctness.

Apply this diff to fix the redundant casting:

        case DATATYPE_I8:
-            ret = (int)(int)
+            ret = (int)
                snprintf(buffer, FORMAT_RESULT_BUFFER_SIZE, formatStr, (CLR_INT64_TEMP_CAST)value->NumericByRef().s8);
            break;
src/CLR/Helpers/nanoprintf/nanoprintf.c (1)

571-574: Typographical correction in comment for clarity

In the comment at line 572:

Integer, character and string

Consider adding a comma after "character" for proper punctuation:

-Integer, character and string
+Integer, character, and string
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 25db559 and 17b98c1.

📒 Files selected for processing (17)
  • CMake/Modules/FindNF_CoreCLR.cmake (3 hunks)
  • src/CLR/CorLib/CorLib.h (1 hunks)
  • src/CLR/CorLib/CorLib.vcxproj (5 hunks)
  • src/CLR/CorLib/corlib_native_System_Number.cpp (1 hunks)
  • src/CLR/Core/Core.vcxproj (2 hunks)
  • src/CLR/Core/Core.vcxproj.filters (1 hunks)
  • src/CLR/Diagnostics/Diagnostics.h (1 hunks)
  • src/CLR/Diagnostics/Diagnostics.vcxproj (4 hunks)
  • src/CLR/Diagnostics/Info_Safeprintf.cpp (1 hunks)
  • src/CLR/Helpers/nanoprintf/nanoprintf.c (1 hunks)
  • src/CLR/Helpers/nanoprintf/nanoprintf.h (1 hunks)
  • targets/AzureRTOS/_common/nanoCLR/nanoCRT.cpp (1 hunks)
  • targets/ChibiOS/_nanoCLR/nanoCRT.cpp (1 hunks)
  • targets/ESP32/_Network/NF_ESP32_OpenThread.cpp (1 hunks)
  • targets/ESP32/_nanoCLR/nanoCRT.cpp (1 hunks)
  • targets/FreeRTOS/_common/nanoCLR/nanoCRT.cpp (1 hunks)
  • targets/TI_SimpleLink/_nanoCLR/nanoCRT.cpp (1 hunks)
🔇 Additional comments (31)
src/CLR/Diagnostics/Diagnostics.h (2)

Line range hint 1-17: Overall changes align with PR objectives, but some clarifications needed.

The changes in this file partially align with the PR objectives by including the nanoprintf.h header, which is likely part of the es-printf library implementation mentioned in the PR summary. However, there are a couple of points that need clarification:

  1. The PR objectives don't mention the VIRTUAL_DEVICE conditional compilation. Could you please explain why this distinction is necessary and how it relates to the es-printf implementation?

  2. The PR summary mentions reverting a previous commit, but this file doesn't show any reverted changes. Are the reverted changes in other files not included in this review?

  3. The commented-out includes weren't mentioned in the PR objectives. It would be helpful to understand if these are related to the changes being made or if they should be addressed separately.

These clarifications will help ensure that the changes fully meet the PR objectives and maintain the overall code quality.

To verify the changes related to the es-printf library implementation, please run the following script:

#!/bin/bash
# Description: Check for es-printf related changes and usage

# Search for es-printf related files
echo "Searching for es-printf related files:"
fd -e c -e h -e cpp "es.*printf"

# Search for nanoprintf usage
echo "Searching for nanoprintf usage:"
rg --type cpp "nanoprintf" -C 2

# Check if there are any other printf-related changes
echo "Checking for other printf-related changes:"
git diff --name-only | xargs rg --type cpp "printf" -C 2

14-16: LGTM. Please verify VIRTUAL_DEVICE usage and add documentation.

The conditional inclusion of nanoprintf.h aligns with the PR objective of reinstating the printf implementation. This change looks good, but there are a couple of points to consider:

  1. Please verify that the VIRTUAL_DEVICE macro is consistently used across the project for distinguishing between virtual and non-virtual device builds.

  2. It would be helpful to add a brief comment explaining why nanoprintf.h is excluded for virtual devices. This will provide context for future maintainers.

To ensure consistent usage of the VIRTUAL_DEVICE macro, please run the following script:

src/CLR/CorLib/CorLib.h (1)

17-19: LGTM! Consider regrouping includes.

The addition of the nanoprintf.h include aligns well with the PR objective of reinstating the printf implementation. The conditional compilation ensures it's only included when not building for a virtual device, which is a good practice for managing different build configurations.

Consider moving this include statement to group it with other similar includes, perhaps after the #include "nanoCRT.h" line. This would improve code organization and readability.

Let's verify the impact of this change on the rest of the codebase:

This script will help us understand how nanoprintf.h is used across the project and identify any potential conflicts or inconsistencies.

✅ Verification successful

Change Verified

The inclusion of nanoprintf.h has been confirmed across the codebase without introducing any conflicts or inconsistencies. The refactor suggestion to regroup the include statement with similar includes remains valid for improved code organization and readability.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential conflicts or inconsistencies with nanoprintf usage

# Test 1: Check if nanoprintf.h exists in the project
echo "Checking if nanoprintf.h exists:"
fd nanoprintf.h

# Test 2: Look for other inclusions of nanoprintf.h
echo "Checking for other inclusions of nanoprintf.h:"
rg '#include.*nanoprintf\.h'

# Test 3: Check for potential conflicts with printf-like functions
echo "Checking for potential conflicts with printf-like functions:"
rg '\b(sprintf|fprintf|printf|snprintf)\b' --type cpp

# Test 4: Check for usage of VIRTUAL_DEVICE macro
echo "Checking for usage of VIRTUAL_DEVICE macro:"
rg 'VIRTUAL_DEVICE' --type cpp

Length of output: 20323

src/CLR/Diagnostics/Info_Safeprintf.cpp (3)

8-8: LGTM: Addition of nanoprintf.h

The inclusion of nanoprintf.h is consistent with the PR objectives of reintroducing the printf implementation from the es-printf library.


14-15: Improved error handling for vsnprintf

The changes to the return type and condition for vsnprintf are correct and beneficial:

  1. Using int instead of size_t for chars matches the return type of vsnprintf.
  2. The new condition chars >= 0 properly checks for encoding errors (negative return) and successful formatting (non-negative return).

These modifications enhance the robustness of the error handling in this function.


17-18: Simplified and improved buffer overflow handling

The changes to the buffer overflow handling are appropriate:

  1. The condition fRes == false correctly identifies both encoding errors and buffer overflows.
  2. Setting chars = (int)iBuffer in case of failure ensures that the entire buffer is marked as used, preventing potential buffer overruns.

This simplification improves the safety and clarity of the function.

src/CLR/Core/Core.vcxproj.filters (1)

Line range hint 1-203: Summary: Change aligns with PR objectives

The addition of nanoprintf.c to the project structure successfully reintroduces the printf implementation as intended. This change is minimal and focused, which is a good practice for pull requests. The file is correctly placed within the "Source Files" filter, ensuring it will be compiled as part of the project.

To ensure that this change doesn't conflict with any existing printf implementations, please run the following verification script:

This script will help verify that we're not introducing conflicting implementations and that nanoprintf.c is the only new printf-related file being added.

✅ Verification successful

To ensure that there are no conflicting printf implementations introduced by adding nanoprintf.c, please run the following verification script:


Verification Successful: No Conflicting printf Implementations Found

The addition of nanoprintf.c successfully integrates the new printf implementation without introducing conflicts. The existing macro definitions appropriately redirect printf calls to nanoprintf, ensuring consistency across the project.

  • nanoprintf.c and nanoprintf.h are correctly added to the "Source Files" filter.
  • No other printf implementations were detected that could conflict with nanoprintf.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any existing printf implementations that might conflict with nanoprintf

# Search for other printf implementations
echo "Searching for other printf implementations:"
rg -i 'printf.*implementation' --type c --type cpp --type h

# Check if nanoprintf.c is the only new printf-related file
echo "Checking for new printf-related files:"
git diff --name-only | grep -i 'printf'

Length of output: 285


Script:

#!/bin/bash
# Description: Comprehensive search for printf implementations and usages to ensure no conflicts with nanoprintf

echo "Searching for printf function definitions or overrides:"
rg -i '^\s*(?:int|void)\s+printf\s*\(' --type c --type cpp --type h

echo "Searching for printf macro definitions:"
rg -i '#\s*define\s+PRINTF' --type c --type cpp --type h

echo "Listing all printf-related files in the repository:"
fd -i 'printf' --type f

Length of output: 1352

src/CLR/Diagnostics/Diagnostics.vcxproj (3)

108-108: LGTM: Consistent changes across all configurations.

The addition of the ..\Helpers\nanoprintf include directory is consistent across all build configurations (Debug|Win32, Debug|x64, Release|Win32, Release|x64). This is a good practice as it ensures the same behavior across different build types.

Also applies to: 121-121, 136-136, 153-153


108-108: Check the order of include directories.

The new include directory ..\Helpers\nanoprintf has been added as the first entry in the AdditionalIncludeDirectories property. While this ensures that the new printf implementation takes precedence, please verify that this order doesn't cause any unintended consequences or conflicts with other headers.

If the script finds any matches, review those files to ensure there are no conflicts between the nanoprintf implementation and standard library headers.

Also applies to: 121-121, 136-136, 153-153

✅ Verification successful

Include directory order verified successfully; no conflicts detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential header conflicts

# Test: Search for files that include both nanoprintf and potentially conflicting headers
rg --type cpp -e '#include.*nanoprintf' -e '#include.*<stdio.h>' -e '#include.*<printf.h>' src/

Length of output: 576


108-108: Verify the necessity of the old include directory.

The old include directory ..\..\..\targets\win32\Include is still present in the AdditionalIncludeDirectories property. Please verify if this directory is still necessary after the introduction of the nanoprintf library.

If the script doesn't find any matches, consider removing the old include directory.

Also applies to: 121-121, 136-136, 153-153

✅ Verification successful

Remove the old include directory ..\..\..\targets\win32\Include from AdditionalIncludeDirectories, as no references were found after introducing the nanoprintf library.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if there are any files in the project that still include headers from the old directory

# Test: Search for includes from the old directory
rg --type cpp -g '!**/nanoprintf/*' '#include.*targets/win32/Include' src/

Length of output: 76


Script:

#!/bin/bash
# Description: Re-verify if any files still include headers from the old directory

# Test: Search for includes from the old directory with corrected pattern
rg --type cpp -e '#include\s*["<]..\..\..\targets/win32/Include[^">]*[">]' src/

Length of output: 81


Script:

#!/bin/bash
# Description: Search for any #include statements referencing the targets/win32/Include directory

# Test: Search for includes from the old directory using a flexible pattern
rg --type cpp '#include\s*["<].*targets/win32/Include[^">]*[">]' src/

Length of output: 71

src/CLR/Core/Core.vcxproj (1)

22-22: LGTM! Verify nanoprintf integration.

The addition of nanoprintf.c to the project is consistent with the PR objective of reinstating the printf implementation. The file is correctly added to the ClCompile item group, ensuring it will be compiled as part of the project.

To ensure the nanoprintf library is properly integrated, please run the following verification script:

This script will help verify the presence of the nanoprintf file, its usage in the project, and potential conflicts with existing printf implementations.

✅ Verification successful

Verified: nanoprintf integration is correct.

The nanoprintf.c file exists at src/CLR/Helpers/nanoprintf/nanoprintf.c and is correctly referenced in the Core.vcxproj file. The integration aligns with the PR objectives, and there are no conflicts with existing printf implementations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the presence and usage of nanoprintf in the project.

# Test 1: Check if the nanoprintf.c file exists
echo "Checking for nanoprintf.c file..."
fd -t f "nanoprintf.c" src/Helpers/nanoprintf

# Test 2: Search for nanoprintf function usage in the project
echo "Searching for nanoprintf usage..."
rg --type cpp "nanoprintf" src

# Test 3: Check for any potential conflicts with existing printf implementations
echo "Checking for potential conflicts..."
rg --type cpp "printf" src | grep -v "nanoprintf"

Length of output: 12646


Script:

#!/bin/bash
# Description: Locate the nanoprintf.c file within the project.

echo "Searching for nanoprintf.c file in the entire project..."
fd -t f "nanoprintf.c" src

Length of output: 189

src/CLR/CorLib/CorLib.vcxproj (1)

155-155: LGTM: Consistent addition of nanoprintf include directory.

The changes consistently add the ..\..\CLR\Helpers\nanoprintf directory to the AdditionalIncludeDirectories property across all configurations (Debug/Release) and platforms (Win32/x64). This is a good practice for maintaining build consistency.

To ensure the nanoprintf directory exists and contains the expected files, please run the following script:

This script will verify the existence of the nanoprintf directory and check for essential files. Please adjust the list of essential files as needed based on the expected contents of the nanoprintf library.

Also applies to: 168-168, 183-183, 200-200

✅ Verification successful

Verified: nanoprintf directory and essential files confirmed.

The ..\..\CLR\Helpers\nanoprintf directory exists and contains the essential files (nanoprintf.c, nanoprintf.h) across all configurations and platforms, ensuring build consistency and intended functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence and contents of the nanoprintf directory

# Check if the directory exists
if [ -d "src/CLR/Helpers/nanoprintf" ]; then
    echo "nanoprintf directory exists."
    # List the contents of the directory
    ls -l src/CLR/Helpers/nanoprintf
else
    echo "Error: nanoprintf directory not found."
    exit 1
fi

# Check for essential files (adjust the list as needed)
essential_files=("nanoprintf.h" "nanoprintf.c")
for file in "${essential_files[@]}"; do
    if [ -f "src/CLR/Helpers/nanoprintf/$file" ]; then
        echo "Found essential file: $file"
    else
        echo "Error: Essential file not found: $file"
        exit 1
    fi
done

echo "Verification complete."

Length of output: 721

CMake/Modules/FindNF_CoreCLR.cmake (4)

271-271: LGTM: nanoprintf directory added to find_file paths.

The addition of the nanoprintf directory to the find_file paths is correct and consistent with the earlier changes. This ensures that the build system can locate the nanoprintf.c file when processing the source files list.


25-25: Summary: Clean integration of nanoprintf library

The changes in this file successfully integrate the nanoprintf library into the NF_CoreCLR build process. The additions include:

  1. A new include directory for nanoprintf headers
  2. The nanoprintf.c source file in the compilation list
  3. The nanoprintf directory in the find_file paths

These changes are consistent, minimal, and follow the existing structure of the CMake module. They should enable the use of nanoprintf functionality in the NF_CoreCLR library without introducing conflicts or issues.

Also applies to: 146-146, 271-271


25-25: LGTM: New include directory for nanoprintf added correctly.

The addition of the nanoprintf include directory is consistent with the existing structure and will allow the compiler to find the necessary header files.

To ensure the directory structure is correct, please run the following command:

#!/bin/bash
# Verify the existence of the nanoprintf directory
if [ -d "${CMAKE_SOURCE_DIR}/src/CLR/Helpers/nanoprintf" ]; then
    echo "nanoprintf directory exists."
else
    echo "nanoprintf directory not found. Please check the path."
fi

146-146: LGTM: nanoprintf.c added to the source files list.

The addition of nanoprintf.c to the NF_CoreCLR_SRCS list is correct and ensures it will be compiled as part of the NF_CoreCLR library.

To confirm the existence of the nanoprintf.c file, please run the following command:

✅ Verification successful

LGTM: nanoprintf.c added to the source files list.

The addition of nanoprintf.c to the NF_CoreCLR_SRCS list is correct and ensures it will be compiled as part of the NF_CoreCLR library.

  • Verified the existence of nanoprintf.c at src/CLR/Helpers/nanoprintf/nanoprintf.c.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of nanoprintf.c
if [ -f "${CMAKE_SOURCE_DIR}/src/CLR/Helpers/nanoprintf/nanoprintf.c" ]; then
    echo "nanoprintf.c file exists."
else
    echo "nanoprintf.c file not found. Please check the path."
fi

Length of output: 159


Script:

#!/bin/bash
# Search for nanoprintf.c in the repository
rg --files | grep 'nanoprintf\.c$'

Length of output: 76

targets/ChibiOS/_nanoCLR/nanoCRT.cpp (2)

8-8: Including <nanoprintf.h> to utilize nanoprintf library

The inclusion of <nanoprintf.h> enables the use of the nanoprintf library, providing efficient and lightweight printf functionalities suitable for embedded systems.


Line range hint 168-187: Document limitations of ASCII-only comparison in hal_stricmp

The hal_stricmp function compares strings in a case-insensitive manner but is limited to ASCII characters and does not consider locale-specific rules or extended character sets.

Ensure that this function is suitable for your application's requirements and add documentation to highlight its ASCII-only limitation.

Would you like assistance in implementing a locale-aware, Unicode-compliant case-insensitive comparison function?

targets/FreeRTOS/_common/nanoCLR/nanoCRT.cpp (1)

8-8: Including <nanoprintf.h> header

The inclusion of <nanoprintf.h> integrates the nanoprintf library, which enhances formatting capabilities. This is appropriate and necessary for the added functionality.

targets/TI_SimpleLink/_nanoCLR/nanoCRT.cpp (2)

8-8: Verify the inclusion of <nanoprintf.h>

Ensure that including <nanoprintf.h> is necessary and that it does not conflict with existing headers or definitions in the project. Confirm that this header provides the required functionality without introducing any redundancy.


Line range hint 13-45: Avoid magic numbers and ensure constants are defined

In the hal_snprintf_float function, constants like HAL_FLOAT_SHIFT and HAL_FLOAT_PRECISION are used. Verify that these constants are defined appropriately and consider replacing magic numbers with well-defined constants or enumerations for better readability and maintainability.

targets/ESP32/_nanoCLR/nanoCRT.cpp (2)

9-9: Including <nanoprintf.h> is appropriate and necessary

The inclusion of <nanoprintf.h> enables the use of the nanoprintf library for formatted printing functionalities, which aligns with the PR objective of adding back the private implementation of printf.


Line range hint 29-89: Verify buffer safety in hal_snprintf_* functions

Ensure that the usage of hal_snprintf within hal_snprintf_float and hal_snprintf_double properly handles the buffer size (len) to prevent potential buffer overflows.

To confirm buffer safety, you can run the following script:

targets/AzureRTOS/_common/nanoCLR/nanoCRT.cpp (5)

9-9: Including <nanoprintf.h> for enhanced formatting capabilities

The inclusion of <nanoprintf.h> integrates the nanoprintf library, which enhances the project's string formatting capabilities.


Line range hint 23-54: Ensure correctness of hal_snprintf_float implementation

The hal_snprintf_float function correctly handles the formatting of fixed-point numbers by separating integer and decimal parts for both positive and negative values. The use of bit manipulation and rounding appears appropriate.


Line range hint 56-87: Verify the implementation of hal_snprintf_double

The hal_snprintf_double function mirrors the logic of hal_snprintf_float, adapting it for double-precision numbers. Ensure that the calculations, especially the bit shifts and rounding mechanisms, handle edge cases correctly.


Line range hint 116-132: Appropriate handling of safe string copy in hal_strcpy_s

The hal_strcpy_s function includes necessary checks for null pointers and buffer sizes, ensuring safe string copying. The use of _ASSERTE(FALSE) helps catch errors during debugging.


Line range hint 135-151: Safe implementation of hal_strncpy_s

The hal_strncpy_s function correctly handles boundary conditions and ensures that the destination string is null-terminated. The checks for null pointers and buffer sizes enhance robustness.

src/CLR/Helpers/nanoprintf/nanoprintf.c (3)

1085-1090: Ensure proper handling of buffer boundaries in doprnt function

The added condition checks if count >= n and breaks out of the loop to prevent writing beyond the buffer size. This change helps in avoiding buffer overflows and ensures that the output stays within the allocated memory.


264-265: ⚠️ Potential issue

Review handling of DBL_MIN in floating-point normalization

In the normalization code for handling edge cases:

else if(number == DBL_MIN)
{
    number = -1.7976931348623157;
    decpt = -309;
}

Assigning a negative value to number when DBL_MIN is the smallest positive normalized double may not be appropriate and could introduce inaccuracies in formatting.

Please verify that the handling of DBL_MIN aligns with the expected behavior for the smallest positive double value. It's important to ensure that the value assigned to number correctly represents DBL_MIN without changing its sign.

Run the following script to double-check constants and usages of DBL_MIN:

#!/bin/bash
# Description: Verify that DBL_MIN is correctly used in the codebase.

# Search for all occurrences of DBL_MIN
rg --type c --word-regexp 'DBL_MIN'

# Check for assignments that may incorrectly alter its sign
rg --type c 'number\s*=\s*-\s*DBL_MIN'

96-98: Verify increased FLOAT_DIGITS value for potential buffer overflows

The macro FLOAT_DIGITS has been increased to 18. Ensure that all related buffer sizes and calculations can accommodate this increased precision without causing buffer overflows or other memory issues, especially in functions that use FLOAT_DIGITS for buffer allocations.

Run the following script to identify buffer allocations and usages dependent on FLOAT_DIGITS:

✅ Verification successful

FLOAT_DIGITS increase does not pose buffer overflow risks

After thorough verification, increasing the FLOAT_DIGITS value to 18 does not affect any buffer sizes or related calculations in the codebase. No potential buffer overflows were identified related to this change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for usages of FLOAT_DIGITS and related buffer sizes.

# Find all occurrences of FLOAT_DIGITS in the codebase
rg --type c --word-regexp 'FLOAT_DIGITS'

# Find buffer declarations that may be affected
rg --type c --regex 'char\s+\w+\[\s*(BUFMAX|DIGITS_MAX_[FEG]|\d+)\s*\]'

# Search for any calculations involving FLOAT_DIGITS that could impact buffer sizes
rg --type c --regex 'BUFMAX\s*[\*\/+-]\s*FLOAT_DIGITS'

Length of output: 340


Script:

#!/bin/bash
# Description: Search for usages of FLOAT_DIGITS and related buffer sizes.

# Find all occurrences of FLOAT_DIGITS in the codebase
rg --type c --word-regexp 'FLOAT_DIGITS'

# Find buffer declarations that may be affected
rg --type c --regex 'char\s+\w+\[\s*(BUFMAX|DIGITS_MAX_[FEG]|\d+)\s*\]'

# Search for any calculations involving FLOAT_DIGITS that could impact buffer sizes
rg --type c --regex 'BUFMAX\s*[\*/+\-]\s*FLOAT_DIGITS'

Length of output: 1387


Script:

#!/bin/bash
# Description: Search for usages of FLOAT_DIGITS and related buffer sizes.

# Find all occurrences of FLOAT_DIGITS in the codebase
rg --type c --word-regexp 'FLOAT_DIGITS'

# Find buffer declarations that may be affected
rg --type c --regexp 'char\s+\w+\[\s*(BUFMAX|DIGITS_MAX_[FEG]|\d+)\s*\]'

# Search for any calculations involving FLOAT_DIGITS that could impact buffer sizes
rg --type c --regexp 'BUFMAX\s*[\*/+\-]\s*FLOAT_DIGITS'

Length of output: 3283


Script:

#!/bin/bash
# Description: Search for buffer declarations and buffer-related function usages involving FLOAT_DIGITS.

# Find buffer declarations where buffer size uses FLOAT_DIGITS
rg --type c --regexp 'char\s+\w+\[\s*.*FLOAT_DIGITS.*\]'

# Find buffer-related function calls that utilize FLOAT_DIGITS for formatting
rg --type c --regexp 'snprintf\s*\(.*FLOAT_DIGITS.*\)'
rg --type c --regexp 'sprintf\s*\(.*FLOAT_DIGITS.*\)'

# Find any other buffer size calculations involving FLOAT_DIGITS
rg --type c --regexp '(BUFMAX|BUFFER_SIZE|SIZE)\s*[\*/+\-]\s*FLOAT_DIGITS'

Length of output: 248

Copy link

@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

🧹 Outside diff range and nitpick comments (6)
src/CLR/Helpers/nanoprintf/nanoprintf.h (2)

72-116: Good configuration options with room for documentation improvement

The memory access and output configuration sections provide excellent flexibility for different platforms. The commented examples for AVR microcontrollers (lines 98-104) offer valuable guidance for platform-specific implementations.

The custom putchar_ function (line 114) allows for easy output redirection, which is great for embedded systems. However, it would be beneficial to add a brief comment explaining the expected behavior of this function for future maintainers.

Consider adding a brief comment above the putchar_ function declaration to explain its purpose and expected implementation.


310-313: Function redefinitions for custom printf implementation

The redefinition of standard printf functions to use custom implementations (lines 310-313) allows for seamless integration of the custom printf functionality. This approach is consistent with the project's requirements, as confirmed in the retrieved learnings.

However, to enhance safety and flexibility, consider wrapping these redefinitions in a conditional compilation block. This would allow users to opt-out of the redefinitions if needed.

Consider wrapping the redefinitions in a conditional compilation block:

+#ifndef NANOPRINTF_NO_REDEFINITION
 #define printf      printf_
 #define sprintf     sprintf_
 #define snprintf    snprintf_
 #define vsnprintf   vsnprintf_
+#endif // NANOPRINTF_NO_REDEFINITION

This change allows users to disable the redefinitions by defining NANOPRINTF_NO_REDEFINITION if they need to use the standard library functions in certain parts of their code.

src/CLR/Helpers/nanoprintf/nanoprintf.c (4)

152-171: LGTM! Consider a small optimization for large numbers.

The count_integer_digits function is well-implemented and correctly handles negative numbers, zero, and positive numbers. It efficiently counts the digits in the integer part of a double.

For very large numbers, consider using logarithms for a more efficient calculation:

 flt_width_t count_integer_digits(double number) {
     // Handle negative numbers
     if (number < 0) {
         number = -number;
     }

     // Handle special case for zero
     if (number < 1.0) {
         return 1;
     }

+    // For large numbers, use logarithm for efficiency
+    if (number >= 1e6) {
+        return (flt_width_t)(floor(log10(number))) + 1;
+    }

     flt_width_t count = 0;

     while (number >= 1.0) {
         number /= 10.0;
         count++;
     }

     return count;
 }

This optimization would be more efficient for very large numbers, while still using the current method for smaller numbers.


300-311: LGTM! Consider adding a comment for clarity.

The changes to format_float function correctly handle the case when the number is an integer. This is a good optimization to avoid unnecessary decimal places for integer values.

Consider adding a brief comment explaining the purpose of this check:

 // [NF_CHANGE]

+// Special handling for integer values to avoid unnecessary decimal places
 // check if number is integer
 if (number == (int)number)
 {
     // number is an integer

     // set number of digits required to have 0 decimal places
     ndigits = count_integer_digits(number);
 }

 // [END_NF_CHANGE]

This comment would help future maintainers understand the purpose of this optimization quickly.


1261-1278: LGTM! Consider adding error handling for edge cases.

The snprintf_ function is well-implemented, correctly handling the buffer size limit and ensuring null-termination. It properly uses doprnt for formatting and returns the correct count.

Consider adding error handling for the case when n is 0:

 printf_t snprintf_(char *buf, size_t n,const char *fmt, ... )
 {
     va_list ap;
     int count;

+    // Handle edge case where buffer size is 0
+    if (n == 0) {
+        return 0;
+    }

     va_start(ap, fmt);
     count = doprnt(&buf, putbuf, n - 1, fmt, ap);
     va_end(ap);

     // Append null terminator if there's space.
-    if (n > 0)
-    {
-        *buf = '\0';
-    }
+    *buf = '\0';
     
    return count;
 }

This change ensures that the function behaves correctly even when given a buffer of size 0, and simplifies the null-termination logic.


1288-1314: LGTM! Consider simplifying null-termination logic.

The vsnprintf_ function is well-implemented, correctly using va_copy, doprnt, and handling buffer size limits. It properly ensures null-termination and returns the correct count.

Consider simplifying the null-termination logic and adding a check for buffer size 0:

 printf_t vsnprintf_(char *buffer, size_t bufsz, char const *format, va_list vlist)
 {
     size_t count;
     va_list vlistCopy;

+    // Handle edge case where buffer size is 0
+    if (bufsz == 0) {
+        return 0;
+    }

     // Create a copy of the variable argument list
     va_copy(vlistCopy, vlist);

     // Perform the actual formatting operation
-    count = doprnt(&buffer, putbuf, bufsz, format, vlistCopy);
+    count = doprnt(&buffer, putbuf, bufsz - 1, format, vlistCopy);

     // append null terminator
-    if(count < bufsz)
-    {
-        buffer[count] = '\0';
-    }
-    else
-    {
-        buffer[bufsz - 1] = '\0';
-    }
+    buffer[count < bufsz - 1 ? count : bufsz - 1] = '\0';

     // Clean up the copied variable argument list
     va_end(vlistCopy);

     return count;
 }

These changes simplify the null-termination logic, ensure that we always leave space for the null terminator when calling doprnt, and handle the edge case of a 0-size buffer.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 68f9e6e and 8a40e1b.

📒 Files selected for processing (2)
  • src/CLR/Helpers/nanoprintf/nanoprintf.c (1 hunks)
  • src/CLR/Helpers/nanoprintf/nanoprintf.h (1 hunks)
🧰 Additional context used
📓 Learnings (3)
📓 Common learnings
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
src/CLR/Helpers/nanoprintf/nanoprintf.c (1)
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
src/CLR/Helpers/nanoprintf/nanoprintf.h (1)
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
🔇 Additional comments (5)
src/CLR/Helpers/nanoprintf/nanoprintf.h (3)

1-70: Well-structured header with flexible type definitions

The file header is well-organized, including proper copyright information and include guards. The custom typedef for printf_t (lines 51-55) provides excellent flexibility, allowing for different return types based on platform requirements. This approach facilitates easy adaptation to various embedded systems.


117-224: Comprehensive and extensible feature flag system

The feature configuration section provides an extensive and well-documented set of feature flags. Each flag is clearly defined with a unique bit, allowing for efficient combination of features. This approach offers fine-grained control over the printf implementation, which is crucial for optimizing performance and code size in embedded systems.

The clear comments for each flag (e.g., lines 150-151, 153-154) make it easy for developers to understand and select the required features for their specific use case.


1-317: Comprehensive and flexible printf implementation for embedded systems

This file provides a well-structured and highly configurable implementation of printf-like functions tailored for embedded systems. The extensive use of feature flags and pre-defined feature sets allows for fine-grained control over functionality and code size, which is crucial for resource-constrained environments.

Key strengths:

  1. Flexible type definitions for different platforms
  2. Comprehensive feature flag system
  3. Pre-defined feature sets for common use cases
  4. Custom output function support

Minor suggestions for improvement have been made, including:

  1. Adding documentation for the custom putchar_ function
  2. Reviewing the NANOFRAMEWORK_SET for potential optimization
  3. Adding a conditional compilation block for function redefinitions

Overall, this implementation is well-suited for the nanoFramework project, providing the necessary flexibility and functionality for various embedded systems.

src/CLR/Helpers/nanoprintf/nanoprintf.c (2)

1281-1285: Clarify the purpose of the putchar_ function.

The putchar_ function is currently implemented as an empty function that does nothing with its input. It's unclear why this function exists in its current form.

Could you provide more context on the intended use of this function? If it's meant to be a placeholder for future implementation, consider adding a TODO comment. If it's intentionally empty for some reason, please add a comment explaining why.

 // [NF_CHANGE]
 void putchar_(char character)
 {
+    // TODO: Implement character output or explain why this function is intentionally empty
     (void)character;
 }
 // [END_NF_CHANGE]

This will help future maintainers understand the purpose of this function.


1-1316: Overall, good improvements to the printf implementation.

The changes in this file enhance the safety and functionality of the printf-like functions. The new count_integer_digits function, modifications to format_float, and the addition of snprintf_ and vsnprintf_ functions are well-implemented and improve the overall robustness of the code.

Some minor suggestions have been made for optimization and clarity:

  1. Consider using logarithms for large numbers in count_integer_digits.
  2. Add explanatory comments for the integer handling in format_float.
  3. Improve error handling in snprintf_ for edge cases.
  4. Clarify the purpose of the empty putchar_ function.
  5. Simplify null-termination logic in vsnprintf_.

These changes will further improve the code's efficiency, readability, and maintainability.

Copy link

@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

🧹 Outside diff range and nitpick comments (1)
src/CLR/Helpers/nanoprintf/nanoprintf.c (1)

1-1: Remove Byte Order Mark (BOM) from the start of the file

The file begins with a Byte Order Mark (BOM) character before the comment on line 1. This can cause issues with compilers or tools that do not expect a BOM. Please remove the BOM to ensure compatibility across different environments.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8a40e1b and b3afd91.

📒 Files selected for processing (1)
  • src/CLR/Helpers/nanoprintf/nanoprintf.c (1 hunks)
🧰 Additional context used
📓 Learnings (2)
📓 Common learnings
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
src/CLR/Helpers/nanoprintf/nanoprintf.c (1)
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.

Copy link

@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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b3afd91 and af04c1d.

📒 Files selected for processing (2)
  • src/CLR/CorLib/corlib_native_System_Number.cpp (2 hunks)
  • src/CLR/Helpers/nanoprintf/nanoprintf.c (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/CLR/CorLib/corlib_native_System_Number.cpp
🧰 Additional context used
📓 Learnings (2)
📓 Common learnings
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
src/CLR/Helpers/nanoprintf/nanoprintf.c (1)
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
🔇 Additional comments (2)
src/CLR/Helpers/nanoprintf/nanoprintf.c (2)

1243-1246: Clarify the purpose of the empty putchar_ function

The putchar_ function is currently implemented as an empty function that does nothing with the input character. This might be intentional, but it's unusual for a function named putchar_ to not actually output the character.

Could you please clarify the purpose of this empty implementation? Is it intended to be a placeholder for future implementation, or is it meant to suppress character output in certain contexts?

If it's a placeholder, consider adding a TODO comment to indicate future implementation plans:

 void putchar_(char character)
 {
+    // TODO: Implement character output or explain why this function is intentionally empty
     (void)character;
 }

1-1278: Summary of nanoprintf.c review

Overall, this file provides a functional implementation of lightweight printf-like functionality. The code demonstrates attention to detail in handling various formatting options and edge cases. However, there are several areas where improvements could be made:

  1. Enhanced buffer overflow protection in snprintf_ and vsnprintf_ functions.
  2. Clarification needed for the empty putchar_ function.
  3. Refactoring opportunities in the format_float function to improve readability and maintainability.
  4. Improvements in overall file structure and organization, including consistent naming conventions, better grouping of related functions, and more comprehensive documentation.

Addressing these points would significantly enhance the code's robustness, readability, and maintainability. Despite these suggestions for improvement, the implementation appears to be functional and well-thought-out in terms of handling various formatting scenarios.

Copy link

@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: 0

🧹 Outside diff range and nitpick comments (1)
src/CLR/Helpers/nanoprintf/nanoprintf.c (1)

1243-1246: Add a comment explaining the empty putchar_ function

The putchar_ function is currently empty. While this might be intentional, it's not immediately clear why. Consider adding a comment explaining the purpose of this empty function to improve code readability and prevent confusion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between af04c1d and e96c6b1.

📒 Files selected for processing (1)
  • src/CLR/Helpers/nanoprintf/nanoprintf.c (1 hunks)
🧰 Additional context used
📓 Learnings (2)
📓 Common learnings
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
src/CLR/Helpers/nanoprintf/nanoprintf.c (2)
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.c:160-570
Timestamp: 2024-10-03T16:46:22.543Z
Learning: The `nanoprintf.c` file contains external code that should not be refactored.
Learnt from: josesimoes
PR: nanoframework/nf-interpreter#3026
File: src/CLR/Helpers/nanoprintf/nanoprintf.h:289-292
Timestamp: 2024-09-30T10:58:31.183Z
Learning: In this project, renaming standard library functions like `printf`, `sprintf`, `snprintf`, and `vsnprintf` to custom implementations is intentional and acceptable.
🔇 Additional comments (2)
src/CLR/Helpers/nanoprintf/nanoprintf.c (2)

1223-1240: Well-implemented snprintf_ function

The snprintf_ function is correctly implemented. It properly handles edge cases, ensures null-termination, and returns the correct count. Good job on following the standard snprintf behavior.


1250-1272: Well-implemented vsnprintf_ function

The vsnprintf_ function is correctly implemented. It properly handles edge cases, ensures null-termination, and returns the correct count. The use of va_copy is a good practice. Well done on following the standard vsnprintf behavior.

@josesimoes josesimoes merged commit c224f7d into main Oct 3, 2024
25 of 29 checks passed
@josesimoes josesimoes deleted the add-back-es-printf branch October 3, 2024 17:18
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