|
doesn't alter the fact that drepper is fundamentally right: you can only handle variable-length data safely if you know its length, and if you know its length then there's no point using functions that rely on null termination. so the only c-string function you should be using is strlen(), when someone else gives you a c string and you need to find out its length in order to start handling it safely. having a "safe" strcpy just encourages people to carry on using c strings for purposes other than interfacing with legacy code.
|
# ? Sep 13, 2015 13:33 |
|
|
# ? Jun 5, 2024 09:31 |
|
Syscalls are legacy code now?
|
# ? Sep 13, 2015 13:47 |
|
what else would you call an interface that was designed decades ago and would be impractical to change?
|
# ? Sep 13, 2015 14:02 |
|
Vanadium posted:Syscalls are legacy code now? The legaciest.
|
# ? Sep 13, 2015 15:11 |
|
Well it's not like they stopped making new syscalls and I haven't really seen anything take not-C strings.
|
# ? Sep 13, 2015 17:19 |
|
i'm saying people shouldn't use c strings in new interfaces. the fact that they do it anyway is beside the point. and it seems likely that consistent string handling within a project leads to fewer bugs overall than trying to use null-terminated strings in some parts and explicit lengths in others, so sticking to c strings might be the right choice for an existing os -- but that's still going to be due to the presence of large amounts of legacy code. linus' main objection that started this whole topic was that changing existing code to use a better interface is inherently dangerous, even if the new interface is theoretically better. Soricidus fucked around with this message at 17:42 on Sep 13, 2015 |
# ? Sep 13, 2015 17:39 |
|
I'd argue that most code does not want "copy this C string but truncate it to this sized C string". It wants "copy up to N bytes of this other buffer into this sized C string". strlcpy might look like it does the latter, but in fact it does the former.
|
# ? Sep 13, 2015 18:02 |
|
Soricidus posted:doesn't alter the fact that drepper is fundamentally right: you can only handle variable-length data safely if you know its length Soricidus posted:and if you know its length then there's no point using functions that rely on null termination. so the only c-string function you should be using is strlen(), when someone else gives you a c string and you need to find out its length in order to start handling it safely. strlcpy (where available) strlen + memcpy/mempcpy/whatever snprintf strncpy I don't know, here strlcpy seems pretty ideal, and there's a well known idiom for checking for truncation. Drepper's arguments are that it's nonstandard, and makes it easy to ignore truncation errors. But he recommends, or did at one time, strlen+mempcpy which I argue is easier to screw up. snprintf (when invoked correctly) is fine but inefficient. It uses the same truncation-check idiom as strlcpy and is standard, but is "vulnerable" to format string exploits if used incorrectly. strncpy doesn't indicate whether truncation occurs and forces an external check, making it easy to skip entirely. Now, in my own code I tend to use length-prefixed strings so the combination of memcpy and snprintf is sufficient. However, I get why the OpenBSD folks implemented strlcpy/strlcat. They do a lot of auditing and fixing of legacy code, including C-string handling code, and strlcpy/strlcat with a termination check is the most-straightforward way to make unsafe code safe. I think the problem in this case is that folks comb through Linux (which, as a whole is newer code than what the OpenBSD audits were dealing with) looking for "strncpy issues" and blindly change up that code without motivation, getting it wrong in the process, and that's what Linus is complaining about. ExcessBLarg! fucked around with this message at 18:13 on Sep 13, 2015 |
# ? Sep 13, 2015 18:09 |
|
Plorkyeran posted:Well yes, strncpy is designed for fixed-length buffers and strlcpy is designed for c strings. The fact that they operate on different data types isn't a problem with either one. The fact that something designed to operate on fixed-length buffers and not strings begins with 'str' seems a bit of a problem.
|
# ? Sep 14, 2015 13:12 |
|
I was looking for a Java ScheduledThreadPoolExecutor implementation that included an exponential backoff policy. I found thiscode:
|
# ? Sep 14, 2015 15:50 |
|
feedmegin posted:The fact that something designed to operate on fixed-length buffers and not strings begins with 'str' seems a bit of a problem.
|
# ? Sep 14, 2015 16:11 |
This code is supposed to shorten inputstring to maxlength characters, by trimming off the end. Supposed to. code:
|
|
# ? Sep 14, 2015 22:00 |
|
Good old off by one errors.
|
# ? Sep 14, 2015 22:06 |
|
C# code:
|
# ? Sep 17, 2015 21:29 |
|
The first horror is that, that timestamp doesn't include a zone offset. I imagine that the result would still be amusing (and probably useless) if it did, though.
|
# ? Sep 17, 2015 22:18 |
|
Bognar posted:
There's a reason DateTimeOffset exists and all new code should use it. ExcessBLarg! posted:The first horror is that, that timestamp doesn't include a zone offset. I imagine that the result would still be amusing (and probably useless) if it did, though. The parsed string does, in fact, include a zone offset ("Z" means Zulu, or UTC, or GMT, or whatever other name we're using today). The default ToString() on a DateTime doesn't include the time zone because timezone information is not included in the DateTime struct. Again, the DateTimeOffset struct was introduced to address this exact shortcoming, and all new code should avoid use of DateTime and only use DateTimeOffset. Dessert Rose fucked around with this message at 22:27 on Sep 17, 2015 |
# ? Sep 17, 2015 22:24 |
|
Aren't there problems with serialization of DateTimeOffsets?
|
# ? Sep 17, 2015 22:30 |
|
fleshweasel posted:Aren't there problems with serialization of DateTimeOffsets? Some cursory searching suggests that XmlSerializer doesn't do it out of the box, but if you use a DataContractSerializer it's fine. You're going to have to do some work either way: you have to send the timezone offset separately if you use a DateTime (or standardize on UTC), or you have to do a little bit of lifting to serialize a DTO properly. Seems like a pretty poor oversight, though.
|
# ? Sep 17, 2015 22:38 |
|
Dessert Rose posted:The default ToString() on a DateTime doesn't include the time zone because timezone information is not included in the DateTime struct. Again, the DateTimeOffset struct was introduced to address this exact shortcoming, and all new code should avoid use of DateTime and only use DateTimeOffset. I agree that DateTimeOffset should be used for capturing timezone information, but don't you think that parsing a time should result in the same representation of that time? If DateTime doesn't have timezone information, then parsing "5:30 AM" should result in 5:30 AM and not be converted based on whatever your local timezone is.
|
# ? Sep 17, 2015 22:41 |
|
Avoid DateTime. DateTimeOffset is better but still very ambiguous and can have many different meanings depending on context. This data type is often re-purposed to mean many different types of time-related concepts. Noda seemingly tries to assign types and remove some ambiguity in handling time for some very common use cases. I looked through it and it looked cool but I haven't used it. http://nodatime.org/ If you use the .Net stdlib time library someone will gently caress up somewhere eventually because rules for time are complicated and shoving this complication into a limited singular data type is a bad idea. If you ask developers how many hours are in a day you'll get the wrong answer enough that it should worry you.
|
# ? Sep 17, 2015 23:12 |
|
Bognar posted:I agree that DateTimeOffset should be used for capturing timezone information, but don't you think that parsing a time should result in the same representation of that time? If DateTime doesn't have timezone information, then parsing "5:30 AM" should result in 5:30 AM and not be converted based on whatever your local timezone is. So I dug deeper. First, I would argue that there is a bug here, but it's simply in DateTime.operator==: code:
code:
To address your argument that it shouldn't be converted to your local timezone, the interface of Parse() is more complicated than you're making it out to be, and if you bothered to read the documentation, you would find that you can get the behavior you want: code:
In summary, time is never as simple as developers want it to be. News at 11. Dessert Rose fucked around with this message at 00:33 on Sep 18, 2015 |
# ? Sep 18, 2015 00:31 |
|
Dessert Rose posted:The default ToString() on a DateTime doesn't include the time zone because timezone information is not included in the DateTime struct. Timestamps without time zones are incredibly annoying. Nearly every time I come across one, I end up wasting a bunch of time figuring out what zone it's in.
|
# ? Sep 18, 2015 03:35 |
|
Bognar posted:
I know i am in a bit late but HUH??? how are you determining DST? both of your datetimes are in GMT so the only way of telling the difference is to manually make it different. shouldnt the strings be 2015-11-01T05:30:00 GMT 2015-11-01T05:30:00 BST as one is GMT (Zulu) the other British Summer Time (dst) MSDN says this C# code:
|
# ? Sep 18, 2015 06:41 |
|
TheresaJayne posted:I know i am in a bit late but HUH??? .NET is converting it from Zulu to his local time, and the second time is after DST ends in the Eastern timezone. Check out Desert Rose's longer post, the DST stuff is explained a little better. Your last bit has only the fact that its a DateTime in common with the post you quoted so I don't know what thats all about.
|
# ? Sep 18, 2015 07:25 |
|
ExcessBLarg! posted:It's "str" because it takes (usually) a C-string as an input. It's also helpful to think of it as the much-less useful inverse function to strncmp. strncpy was designed for a field in a very specific data structure (d_name in dirent), and should never have become part of the general standard C library. Retconning its semantics as being kinda-for-strings, and pretending that it's ok to cpy a str but end up with something that isn't a str, is just whitewashing the fact that it was a mistake. (The API that exposed dirent to user space has long disappeared, happily.)
|
# ? Sep 18, 2015 07:55 |
|
I'm evaluating this commercial Gantt chart library (Bryntum) which seems to be a pretty good library but has one critical flaw: the API documentation (the picky docs) is missing all of the methods that you need to use to actually use the charts. It's bizarre, I go through the examples and see certain methods being used for things like adding new tasks to the chart so I consult the docs and nothing. Not under protected, private, deprecated, removed, the methods that you want to use are just not listed , plenty of other methods and properties you want to use are there -- just not the ones you need to use.
|
# ? Sep 18, 2015 15:24 |
|
Dessert Rose posted:First, I would argue that there is a bug here, but it's simply in DateTime.operator==: I found the same thing when I was playing around with it last night, so it's not as bad as I thought. The equality comparison is still unfortunate though. Dessert Rose posted:To address your argument that it shouldn't be converted to your local timezone, the interface of Parse() is more complicated than you're making it out to be, and if you bothered to read the documentation, you would find that you can get the behavior you want: No need to be a dick about it. I'm well aware of the Parse overloads, but I still don't understand why Parse(string) defaults to converting to local time instead of just setting Kind to Utc. Dessert Rose posted:In summary, time is never as simple as developers want it to be. News at 11. It's hard enough without strange API choices.
|
# ? Sep 18, 2015 15:30 |
|
Working on calendaring software is non-stop horror. Just don't.
|
# ? Sep 18, 2015 16:38 |
|
Bognar posted:No need to be a dick about it. I'm well aware of the Parse overloads, but I still don't understand why Parse(string) defaults to converting to local time instead of just setting Kind to Utc. Sorry, I just have low patience when people call things horrors without doing much research Think about this: if you have a time in any other timezone but your own or UTC, what should happen by default? It has to get converted to something, because DateTime doesn't have offset information. It can only be "local timezone" or "UTC", so it has to pick one. I would argue that, given the rest of the API defaults to local time, converting to local time is consistent with the semantics of DateTime. For example, DateTime.Now returns the local time; you need to call UtcNow if you want UTC, instead of Now returning UTC and LocalNow returning local time. So what should happen if you call Parse with a UTC time? Should it suddenly decide to leave it alone? That would be pretty surprising, because in every other case Parse is converting to local time. If I test my app with a couple random timezones (but not UTC) and see that Parse is converting to local time, I'm going to be pretty mad and probably even post in this thread if it suddenly decides not to convert UTC times. The single-parameter Parse is a convenience method. It's going to make some decisions for you that might not be the right ones, and that's totally fine! That's why you should always look at the other overloads and understand the decisions you can make, that the convenience method is making for you. The lesson here is pay attention to the APIs you're calling. Especially with something as complicated as time, don't assume that the defaults fit your use case.
|
# ? Sep 18, 2015 18:52 |
|
Bognar posted:No need to be a dick about it. I'm well aware of the Parse overloads, but I still don't understand why Parse(string) defaults to converting to local time instead of just setting Kind to Utc.
|
# ? Sep 18, 2015 19:05 |
|
Dessert Rose posted:So what should happen if you call Parse with a UTC time? Should it suddenly decide to leave it alone? That would be pretty surprising, because in every other case Parse is converting to local time. If I test my app with a couple random timezones (but not UTC) and see that Parse is converting to local time, I'm going to be pretty mad and probably even post in this thread if it suddenly decides not to convert UTC times. If the default was for Parse to always return a local time, I would probably agree with you here. However, when a timezone isn't specified it just has a DateTimeKind of Unspecified, which to me sounds appropriate. I think most of the other DateTime methods work in a similar way. To me, though, it seems like if you were supplied with a date where the specified time was UTC, the Kind should be UTC. Really, though, I think the weirdness stems from DateTime attempting to have some limited notion of timezone, when it should have just left it the hell alone. I don't think this problem would have existed if DateTime just strictly parsed a Date and a Time and didn't bother with the kind. Dessert Rose posted:The single-parameter Parse is a convenience method. It's going to make some decisions for you that might not be the right ones, and that's totally fine! That's why you should always look at the other overloads and understand the decisions you can make, that the convenience method is making for you. Totally agreed. I'm mostly just salty that I opened up an ancient project to fix a reported bug and found DateTime.Parse(string) being used *everywhere*. EDIT: To actually answer your question... Dessert Rose posted:Think about this: if you have a time in any other timezone but your own or UTC, what should happen by default? It has to get converted to something, because DateTime doesn't have offset information. DateTime should be used for dates and times in an unspecified timezone. If something with timezone information is being parsed into DateTime, that information should be lopped off entirely and the time shouldn't be converted to anything. That is, that's how I think it should be in my ideal world where DateTime wasn't already screwed up with Kind. Bognar fucked around with this message at 19:22 on Sep 18, 2015 |
# ? Sep 18, 2015 19:13 |
|
The duplicate hour messing up times that don't use it is fun. What happens when you try to specify a 1:30AM that's leapt forward over? Would 1:45 and 1:15 collapse to the same UTC time?
|
# ? Sep 18, 2015 19:26 |
|
Looks like it'll happily represent DateTimes that didn't happen and adding/subtracting minutes doesn't jump out of the invalid range.C# code:
|
# ? Sep 18, 2015 20:13 |
|
Subjunctive posted:strncpy was designed for a field in a very specific data structure (d_name in dirent), and should never have become part of the general standard C library. I suspect the reason strncpy was included in ANSI C is because, at that time, it was regularly used for it's original and intended purpose. How is that a mistake? Subjunctive posted:Retconning its semantics as being kinda-for-strings, and pretending that it's ok to cpy a str but end up with something that isn't a str, is just whitewashing the fact that it was a mistake. The C Programming Language posted:char *strncpy(s,ct,n): copy at most n characters of string ct to s; return s. Pad with '\0's if t has fewer than n characters.
|
# ? Sep 18, 2015 20:23 |
|
Munkeymon posted:Looks like it'll happily represent DateTimes that didn't happen and adding/subtracting minutes doesn't jump out of the invalid range. Interestingly, calling notime.ToUniversalTime() also works, but using TimeZoneInfo.ConvertTimeToUtc(notime, TimeZoneInfo.Local) throws an exception.
|
# ? Sep 18, 2015 20:27 |
|
ExcessBLarg! posted:I suspect the reason strncpy was included in ANSI C is because, at that time, it was regularly used for it's original and intended purpose. How is that a mistake? It was a mistake IMO to have a function that starts with str and doesn't always produce C strings, because all the other ones do and C strings are perilous enough to work with without that footgun sitting on the shelf. There is a false and dangerous symmetry between strcat/strcpy and strncat/strncpy. bufncpy or something would be better. You could even specify the terminator, so that it could actually be used with 0x20-padded FAT records, unlike strncpy. (It's also the only str-function that writes to the target buffer beyond the extent of string-including-terminator, I think.)
|
# ? Sep 18, 2015 23:17 |
|
Speaking of strings, what the hell kind of string comparison function is this:code:
|
# ? Sep 18, 2015 23:50 |
|
Nippashish posted:Speaking of strings, what the hell kind of string comparison function is this: A regrettable one.
|
# ? Sep 19, 2015 00:02 |
|
Subjunctive posted:It was a mistake IMO to have a function that starts with str and doesn't always produce C strings, I don't think they're bad functions, aside from strncat which is difficult to use safely--enough so that it's equivalently bad to strcat for me. strncpy and strncmp though are still useful when having to marshal to fixed-length string records. If you object to the "strn" prefix, fair enough, but I don't think the presence of those functions in the standard library is otherwise unreasonable, especially compared much greater warts in the library (gets, strtok, all the non-reentrant ones, etc.).
|
# ? Sep 19, 2015 00:03 |
|
|
# ? Jun 5, 2024 09:31 |
|
the problem is that people are using the C standard library string functions ityool 2015. this is bad and they should stop doing so except where absolutely necessary. it really doesn't matter what the functions were designed for or how safe your "safe strcpy replacement" is. C strings are a mess that can't be fixed. it's time to put them down.
|
# ? Sep 19, 2015 00:57 |