-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
[rtext] Use libc for TextLength()
, TextCopy()
, TextSubtext()
and TextInsert()
#4911
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
Conversation
if ((src != NULL) && (dst != NULL)) | ||
// strcpy is marked restrict, meaning src and dst must not alias. | ||
// Attempt to defend against that, but this is not fully robust | ||
// as someone could pass in two sub-portions of the same string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note that this is also already a problem with the preexisting code, so we aren't necessarily regressing here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function prototype of TextCopy should probably be marked restrict since strcpy already is. Alternative is to use memmove instead of strcpy to protect against aliasing.
Copy does implicitly signal that two non-overlapping memory regions should be used, however there is risk that some developer has used this function to copy into overlapping memory regions. Strcpy will break such code, whilst memmove will not.
Alternate suggested code:
bytes = strlen(src);
memmove(dst, src, bytes);
This is a reduced version of #3362 that avoids all the stylistic changes of that PR, and also does not change Test Plan: #include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_TEXT_BUFFER_LENGTH 1024
unsigned int TextLength(const char *text)
{
unsigned int length = 0;
if (text != NULL)
{
length = strlen(text);
}
return length;
}
int TextCopy(char *dst, const char *src)
{
int bytes = 0;
// strcpy is marked restrict, meaning src and dst must not alias.
// Attempt to defend against that, but this is not fully robust
// as someone could pass in two sub-portions of the same string.
if ((src != NULL) && (dst != NULL) && (src != dst))
{
strcpy(dst, src);
bytes = strlen(src);
}
return bytes;
}
const char *TextSubtext(const char *text, int position, int length)
{
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
int textLength = TextLength(text);
if (position >= textLength)
{
return buffer; //First char is already '\0' by memset
}
int maxLength = textLength - position;
if (length > maxLength) length = maxLength;
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
memcpy(buffer, text + position, length);
buffer[length] = '\0';
return buffer;
}
char *TextInsert(const char *text, const char *insert, int position)
{
int textLen = TextLength(text);
int insertLen = TextLength(insert);
char *result = (char *)malloc(textLen + insertLen + 1);
memcpy(result, text, position);
memcpy(result + position, insert, insertLen);
memcpy(result + position + insertLen, text + position, textLen - position);
result[textLen + insertLen] = '\0'; // Make sure text string is valid!
return result;
}
int main() {
const char *e = "";
const char *a = "foo";
const char *b = "bars";
printf("%u\n", TextLength(e));
printf("%u\n", TextLength(a));
printf("%u\n", TextLength(b));
char buf[4] = { 0 };
int ret = TextCopy(buf, a);
printf("%d %s\n", ret, buf);
printf("%s\n", TextSubtext(b, 1, 0));
printf("%s\n", TextSubtext(b, 1, 10));
char *j = TextInsert(a, b, 2);
printf("%s\n", j);
free(j);
return 0;
} Result:
|
awesome, please merge this for 6.0 <3. Line 77 in 82c87d1
|
TextLength()
, TextCopy()
, TextSubtext()
and TextInsert()
Unless there is any specific reason to have the length be of unsigned int (4 bytes), the entire TextLength function could be deprecated since it's literally just manual strlen, missing out on all vectorization and intrinsic functions. |
Those functions were created as custom alternatives to libc implementations, also for educational pourposes. There is no plan to replace them by libc implementations. Users wanting libc alternatives can use libc directly. |
Line 1174 in 63b988a
Line 1310 in 63b988a
I feel like |
@jestarray I'm reviewing those ones... EDIT: Sorry, I'm seeing that it will break consistency, |
You can flag the function as a const function pointer, but you may have to break a little ABI a bit since you used int as return value for measureText. Example: https://godbolt.org/z/jsG4zqs3b Alternatively you can skirt with UB by casting the pointer to strlen as (int (*)(const char *)&strlen. Because of the C standard, you can bind the example to STDC_VERSION since strlen is a guarantee by libc, which is guaranteed by standard, if that's wanted. |
No description provided.