Bug 1393 – Phobos needs strnlen()

Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D1 (retired)
Platform
x86
OS
Linux
Creation time
2007-07-31T21:34:00Z
Last change time
2014-02-16T15:22:13Z
Assigned to
bugzilla
Creator
cdunn2001

Comments

Comment #0 by cdunn2001 — 2007-07-31T21:34:14Z
std.c.string needs strnlen(). Here is why: struct Person{ char name[32]; char addr[128]; }; A bunch of these could be stored on disk. After loading, we want to compare 'name' to another array. But how? We can use strncmp(), but we need to know the length of 'name'. It is NOT 32. We cannot use strlen() safely on 'name' because it might not be null-terminated. We need to do this: --- int compare(char[] lhs, char[] rhs){ char* lptr = cast(char*)lhs; char* rptr = cast(char*)rhs; ulong len_lhs = strnlen(lptr, lhs.length); ulong len_rhs = strnlen(rptr, rhs.length); int comp = std.c.string.strncmp(lptr, rptr, min!(uint)(len_lhs, len_rhs)); if (comp) return comp; if (len_lhs < len_rhs) return -1; else if (len_lhs > len_rhs) return 1; else return 0; } bool foo(Person* p){ return !compare(p.name, "Christopher"); } --- Of course, std.string.strlen(char[] s) could also be useful. It should return the length to the first null, or s.length. And my compare() function could be there too. But those are not critical. strnlen() is. If it's not there, people will use strlen() and cause buffer overflows. From the Linux man page: ------------------------ SYNOPSIS #include <string.h> size_t strnlen(const char *s, size_t maxlen); DESCRIPTION The strnlen function returns the number of characters in the string pointed to by s, not including the terminating '\0' character, but at most maxlen. In doing this, strnlen looks only at the first maxlen characters at s and never beyond s+maxlen. RETURN VALUE The strnlen function returns strlen(s), if that is less than maxlen, or maxlen if there is no '\0' character among the first maxlen characters pointed to by s. CONFORMING TO This function is a GNU extension. ----------- And here is a simple implementation: ulong strnlen(char* s, ulong maxlen){ for(ulong i=0; i<maxlen; ++i){ if (!s[i]) return i; } return maxlen; } [I used ulong, since a UNIX string could be an entire file.]
Comment #1 by cdunn2001 — 2007-08-14T20:10:06Z
Derek Parnell suggested slicing as a solution: import std.string; /** Return a slice of the leftmost portion of 'x' up to but not including the first 'c' */ string lefts(string x, char c) { int p; p = std.string.find(x,c); if (p < 0) p = x.length; return x[0..p]; } int compare(string lhs, string rhs, char d = '\0') { return std.string.cmp( lefts(lhs,d), lefts(rhs,d) ); } and use it like ... char[32] NameA = '\0'; char[56] NameB = '\0'; NameA[0..5] = "derek"; NameB[0..7] = "parnell"; result = compare(NameA, NameB); This is simple enough for me.