Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions bots/c/client_lib/inc/core_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -271,10 +272,11 @@ t_unit_config *core_get_unitConfig(t_unit_type type);
// ----- DEBUG FUNCTIONS -----

/// @brief Add debug information to an object for visualization
/// @details This function accumulates debug strings for objects. Multiple calls per tick will append the strings (with newlines).
/// @details This function accumulates debug strings for objects. Multiple calls per tick will append the strings.
/// @param obj The object to attach debug info to
/// @param info The debug string to add
void core_debug_addObjectInfo(const t_obj *obj, const char *info);
/// @param format printf-style format debug string to add
/// @param ... Format arguments matching the format string
void core_debug_addObjectInfo(const t_obj *obj, const char *format, ...);
Comment on lines 274 to +279
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

@details "(with newlines)" is misleading

The implementation in debug.c concatenates messages with no automatic newline between them — callers must embed \n in their format string (as in the PR example). The parenthetical "(with newlines)" suggests the function does it automatically, which could mislead future users.

📝 Suggested clarification
-/// `@details` This function accumulates debug strings for objects. Multiple calls per tick will append the strings (with newlines).
+/// `@details` This function accumulates debug strings for objects. Multiple calls per tick will append the strings. Include `\n` in the format string to separate entries.
📝 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
/// @brief Add debug information to an object for visualization
/// @details This function accumulates debug strings for objects. Multiple calls per tick will append the strings (with newlines).
/// @param obj The object to attach debug info to
/// @param info The debug string to add
void core_debug_addObjectInfo(const t_obj *obj, const char *info);
/// @param format printf-style format debug string to add
/// @param ... Format arguments matching the format string
void core_debug_addObjectInfo(const t_obj *obj, const char *format, ...);
/// `@brief` Add debug information to an object for visualization
/// `@details` This function accumulates debug strings for objects. Multiple calls per tick will append the strings. Include `\n` in the format string to separate entries.
/// `@param` obj The object to attach debug info to
/// `@param` format printf-style format debug string to add
/// `@param` ... Format arguments matching the format string
void core_debug_addObjectInfo(const t_obj *obj, const char *format, ...);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bots/c/client_lib/inc/core_lib.h` around lines 274 - 279, The documentation
for core_debug_addObjectInfo is misleading about newlines; update the `@details`
text in core_lib.h to state that messages are concatenated without automatic
newlines and that callers must include "\n" in their format strings (matching
the debug.c behavior), referencing the function name core_debug_addObjectInfo so
maintainers can find and keep the comment consistent with the implementation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

realloc null-check missing in the implementation — potential crash

In bots/c/client_lib/src/public/debug.c (lines 70–75), the append path overwrites entry->info with the return value of realloc before checking for NULL:

entry->info = realloc(entry->info, old_len + new_len + 1);
strcat(entry->info, msg);   // UB / crash if realloc returned NULL
free(msg);

If realloc fails it returns NULL, the original entry->info pointer is lost (memory leak), and the subsequent strcat(NULL, msg) is undefined behaviour.

🐛 Proposed fix
-    entry->info = realloc(entry->info, old_len + new_len + 1);
-    strcat(entry->info, msg);
-    free(msg);
+    char *tmp = realloc(entry->info, old_len + new_len + 1);
+    if (!tmp)
+    {
+        free(msg);
+        return;
+    }
+    entry->info = tmp;
+    strcat(entry->info, msg);
+    free(msg);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bots/c/client_lib/inc/core_lib.h` at line 279, The append path in
core_debug_addObjectInfo assigns realloc() result directly to entry->info and
then calls strcat(entry->info, msg), which can dereference NULL if realloc
fails; change the logic to call realloc into a temporary pointer (e.g. char
*new_buf = realloc(entry->info, old_len + new_len + 1)), check new_buf for NULL
before updating entry->info, handle the allocation failure (log via existing
debug logger or skip append and still free(msg) to avoid leaks), and only call
strcat on entry->info after the successful realloc; ensure msg is freed in both
success and failure paths.


/// @brief Add a step to the end of the debug path of an object for visualization
/// @param unit The unit to attach the debug path step to
Expand Down
40 changes: 34 additions & 6 deletions bots/c/client_lib/src/public/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,51 @@ static t_debug_entry *core_static_findOrCreateEntry(unsigned long object_id)
return entry;
}

void core_debug_addObjectInfo(const t_obj *obj, const char *info)
void core_debug_addObjectInfo(const t_obj *obj, const char *format, ...)
{
if (!obj || !info) return;
if (!obj || !format) return;

t_debug_entry *entry = core_static_findOrCreateEntry(obj->id);
if (!entry) return;

// format the new info string
va_list ap;
va_start(ap, format);

va_list ap2;
va_copy(ap2, ap);

int needed = vsnprintf(NULL, 0, format, ap);
va_end(ap);

if (needed < 0)
{
va_end(ap2);
return;
}

char *msg = (char *)malloc((size_t)needed + 1);
if (!msg)
{
va_end(ap2);
return;
}

vsnprintf(msg, (size_t)needed + 1, format, ap2);
va_end(ap2);

// append to debug info
if (entry->info == NULL)
{
// First info for this object
entry->info = strdup(info);
entry->info = msg;
}
else
{
size_t old_len = strlen(entry->info);
size_t new_len = strlen(info);
size_t new_len = strlen(msg);
entry->info = realloc(entry->info, old_len + new_len + 1);
strcat(entry->info, info);
strcat(entry->info, msg);
free(msg);
Comment on lines 74 to +78
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

realloc result must not be stored directly into entry->info.

If realloc returns NULL, the original entry->info allocation is lost (memory leak) and the subsequent strcat(NULL, msg) is undefined behavior. Additionally, since msg is a new allocation introduced by this PR, it is also leaked on this failure path.

🐛 Proposed fix
 		size_t old_len = strlen(entry->info);
-		size_t new_len = strlen(msg);
-		entry->info = realloc(entry->info, old_len + new_len + 1);
-		strcat(entry->info, msg);
-		free(msg);
+		size_t new_len = (size_t)needed;
+		char *tmp = realloc(entry->info, old_len + new_len + 1);
+		if (!tmp)
+		{
+			free(msg);
+			return;
+		}
+		entry->info = tmp;
+		memcpy(entry->info + old_len, msg, new_len + 1);
+		free(msg);
📝 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
size_t old_len = strlen(entry->info);
size_t new_len = strlen(info);
size_t new_len = strlen(msg);
entry->info = realloc(entry->info, old_len + new_len + 1);
strcat(entry->info, info);
strcat(entry->info, msg);
free(msg);
size_t old_len = strlen(entry->info);
size_t new_len = (size_t)needed;
char *tmp = realloc(entry->info, old_len + new_len + 1);
if (!tmp)
{
free(msg);
return;
}
entry->info = tmp;
memcpy(entry->info + old_len, msg, new_len + 1);
free(msg);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bots/c/client_lib/src/public/debug.c` around lines 74 - 78, The current code
assigns realloc() directly to entry->info which can lose the original pointer on
failure and cause undefined behavior when calling strcat(entry->info, msg);
change this to use a temporary pointer (e.g., char *tmp = realloc(entry->info,
old_len + new_len + 1)); check if tmp is NULL and if so free msg and handle the
error (return or set an error code) without modifying entry->info; on success
assign entry->info = tmp and then call strcat(entry->info, msg) and free(msg).
Ensure you reference and update the existing variables entry->info, msg,
old_len, new_len and the calls to realloc and strcat in this block.

}
}

Expand Down
3 changes: 2 additions & 1 deletion bots/c/hardcore/my-core-bot/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ void ft_on_tick(unsigned long tick)
core_action_move(own_team_warriors[i], path.steps[0]);
}

core_debug_addObjectInfo(own_team_warriors[i], "Moving towards opponent core :D\n");
core_debug_addObjectInfo(own_team_warriors[i], "Moving towards opponent core at [%d,%d] :D\n",
ft_get_core_opponent()->pos.x, ft_get_core_opponent()->pos.y);
core_action_attack(own_team_warriors[i], ft_get_core_opponent());

// Clean up
Expand Down
4 changes: 4 additions & 0 deletions bots/c/softcore/my-core-bot/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ void ft_on_tick(unsigned long tick)

t_obj **units = ft_get_units_own();
for (int i = 0; units && units[i]; i++)
{
core_action_pathfind(units[i], ft_get_core_opponent()->pos);
core_debug_addObjectInfo(units[i], "I am a warrior! 🗡️ - I am heading for the opponent core at [%d,%d]! 🏰\n",
ft_get_core_opponent()->pos.x, ft_get_core_opponent()->pos.y);
}
free(units);
}
6 changes: 4 additions & 2 deletions wiki/reference/debug/core_debug_addObjectInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ https://github.com/42core-team/monorepo/blob/dev/bots/c/client_lib/src/public/de

Attaches an arbitrary string to any object (typically an object or your core) that will be displayed in the object's tooltip if someone hovers over the object in the visualizer. May be helpful for a variety of debugging purposes.

You can also format strings dynamically by using the function the same way as one would use `printf`. All flags work as normal. Check out the example below for details.

This function can be called multiple times in a given tick, all of the string the function is called with will be appended together at the end.

> [!WARNING]
Expand All @@ -20,7 +22,7 @@ This function can be called multiple times in a given tick, all of the string th
## Signature

```c
void core_debug_addObjectInfo(const t_obj *obj, const char *info);
void core_debug_addObjectInfo(const t_obj *obj, const char *format, ...);
```

## Parameters
Expand All @@ -37,7 +39,7 @@ void
```c
if (path.length > 0)
core_action_move(own_team_warriors[i], path.steps[0]);
core_debug_addObjectInfo(own_team_warriors[i], "Moving towards opponent core\n");
core_debug_addObjectInfo(units[i], "I am a warrior! 🗡️ - I am heading for the opponent core at [%d,%d]! 🏰\n", ft_get_core_opponent()->pos.x, ft_get_core_opponent()->pos.y);
core_action_attack(own_team_warriors[i], ft_get_core_opponent());
```

Expand Down
Loading