On 9/5/23 16:57, Eric Blake wrote: > On Tue, Sep 05, 2023 at 11:09:02AM +0100, Richard W.M. Jones wrote: >>>> +static inline int64_t >>>> +human_size_parse (const char *str, >>>> + const char **error, const char **pstr) >>>> +{ >>>> + int64_t size; >>>> + char *end; >>>> + uint64_t scale = 1; >>>> + >>>> + /* XXX Should we also parse things like '1.5M'? */ >>>> + /* XXX Should we allow hex? If so, hex cannot use scaling suffixes, >>>> + * because some of them are valid hex digits. >>>> + */ >>>> + errno = 0; >>>> + size = strtoimax (str, &end, 10); >>> >>> (1) A further improvement here (likely best done in a separate patch) >>> could be to change the type of "size" to "intmax_t", from "int64_t". >>> That way, the assignment will be safe even theoretically, *and* the >>> overflow check at the bottom of the function (with the division & >>> comparison of the quotient against INT_MAX) will work just the same. >> >> I'm always very unsure how this all works. In particular I seem to >> recall that intmax_t is no longer really the maximum possible int >> (because of int128) and so it's always 64 bit on platforms we care >> about. Can Eric comment? > > intmax_t was supposed to be whatever the compiler supports as its > largest integer type; but you are right that when gcc added > __int128_t, they did NOT change intmax_t at the time (arguably by > using weasel-words that as an implementation-defined type, it was not > an integer type merely because you can't write integer literals of > that type, even though it behaves integral in every other aspect). > We're kind of in a frozen state where making intmax_t larger than 64 > bits will break more programs than expected because it has ABI > implications: > > https://stackoverflow.com/questions/21265462/why-in-g-stdintmax-t-is-not-a-int128-t
The fact (which I just learned today) that ABIs are unable to keep up with intmax_t is a disaster, and entirely defeats the purpose of intmax_t. > > My personal preference is to avoid intmax_t, as it has too much > baggage (the risk of future widening, vs. NOT being the widest type > after all), similar to how size_t already has baggage. In short, > having something that is not platform specific is easier to reason > about (for the same way that using size_t gives me more grief than > directly using int32_t or int64_t; even though size_t is such a > naturally occuring type, the fact that it is not uniform width makes > it trickier to work with). Very painful disconnect between platforms (which prefer fixed size integers) and the C standard (which defines all the rules with standard integer types). > >>>> + >>>> + if (INT64_MAX / scale < size) { >>>> + *error = "could not parse size: size * scale overflows"; >>>> + *pstr = str; >>>> + return -1; >>>> + } > > And thus I prefer that this comparison stay pegged to INT64_MAX, and > not INT_MAX. > Side comment: I never suggested INT64_MAX be replaced with INTMAX_MAX here, and that was deliberate on my part. I only suggested changing the type of "size" from "int64_t" to "intmax_t", so that "size"'s type would literally match the retval type of strtoimax(). And after such a type change, the expression (INT64_MAX / scale < size) would remain exactly right: - All the participating values remain nonnegative, so whatever usual arithmetic conversions are taken, the values will never change. - Keeping the INT64_MAX limit continues to make sure that the final (size * scale) product, although its type *might* change, will produce the same safe value, for returning through an int64_t. (We'd not want the retval type to change!) ... Ahhh! I now see where the confusion comes from. My mistake! I wrote: > That way, the assignment will be safe even theoretically, *and* the > overflow check at the bottom of the function (with the division & > comparison of the quotient against INT_MAX) will work just the same. That's a terrible typo! I meant to write INT64_MAX! Laszlo _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://listman.redhat.com/mailman/listinfo/libguestfs