[libvirt] [PATCH 1/3] conf: Properly truncate wide character names in virDomainObjGetShortName
John Ferlan
jferlan at redhat.com
Fri Aug 25 12:53:13 UTC 2017
On 08/25/2017 02:30 AM, Martin Kletzander wrote:
> On Wed, Aug 23, 2017 at 04:47:03PM -0400, John Ferlan wrote:
>>
>>
>> On 08/23/2017 07:47 AM, Martin Kletzander wrote:
>>> We always truncated the name at 20 bytes instead of characters. In
>>> case 20 bytes were in the middle of a multi-byte character, then the
>>> string became invalid and various parts of the code would error
>>> out (e.g. XML parsing of that string). Let's instead properly
>>> truncate it after 20 characters instead.
>>>
>>> In some cases the truncation didn't even work (as can be seen from the
>>> modified tests), which is fixed by this as well.
>>
>> Didn't work as well? Try at all...
>>
>> As a test I changed the name of pcie-expander-bus to 80 characters and
>> all 80 were printed. I think this goes against your original intention
>> of a shortname...
>>
>>>
>>> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1448766
>>>
>>> Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
>>> ---
>>> src/conf/domain_conf.c | 30
>>> +++++++++++++++++++---
>>> .../qemuxml2argv-aarch64-virt-default-nic.args | 2 +-
>>> .../qemuxml2argv-hugepages-pages2.args | 4 +--
>>> .../qemuxml2argv-hugepages-pages3.args | 5 ++--
>>> .../qemuxml2argv-hugepages-pages5.args | 4 +--
>>> .../qemuxml2argv-hugepages-pages6.args | 2 +-
>>> .../qemuxml2argv-pcie-expander-bus.args | 2 +-
>>> 7 files changed, 37 insertions(+), 12 deletions(-)
>>>
>>
>> Can we add a multibyte name test? These just modify existing tests (I
>> think wrongly too).
>>
>
> Good point, I don't know why I didn't add one. I created one especially
> for testing this, but didn't add it to the repo it seems. However I'm
> not sure we will be able to force the characters to be multibyte, we
> would have to modify the locale of the test, but also skip the test if
> the NLS for the filesystem is something like ISO 8859-1 or so. I can
> add one anyway, at least on some systems it might check for something.
>
>>
>>> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
>>> index 47eba4dbb315..9a46ceece2d6 100644
>>> --- a/src/conf/domain_conf.c
>>> +++ b/src/conf/domain_conf.c
>>> @@ -27131,6 +27131,8 @@ virDomainDefHasMemballoon(const virDomainDef
>>> *def)
>>> }
>>>
>>>
>>> +#define VIR_DOMAIN_SHORT_NAME_MAX 20
>>> +
>>> /**
>>> * virDomainObjGetShortName:
>>> * @vm: Machine for which to get a name
>>> @@ -27141,15 +27143,37 @@ virDomainDefHasMemballoon(const
>>> virDomainDef *def)
>>> char *
>>> virDomainObjGetShortName(const virDomainDef *def)
>>> {
>>> - const int dommaxlen = 20;
>>> + wchar_t wshortname[VIR_DOMAIN_SHORT_NAME_MAX + 1] = {0};
>>> + size_t len = 0;
>>> + char *shortname = NULL;
>>> char *ret = NULL;
>>>
>>
>> It would seem that we could figure there were multibyte chars in the
>> name "if strlen(def->name) != mbstowcs(NULL, def->name, 0)" and not do
>> any conversion, leaving the old code "as is" (mostly) and then
>> implementing something for these wide characters.
>>
>
> Good point, we can do that.
>
>> Of course I'm not getting anything other than -1 returned for the
>> mbstowcs and I didn't really want to dig any further, so I leave it up
>> to you!
>>
>
> What the errno in that case?
>
"Invalid or incomplete multibyte or wide character"
Same message even after adding a virGettextInitialize call in the
function as a test... It was one of those annoying end of the day
things too - as in this *should* work, why is it not working.
>> I tried to modify the same test and change the name to "ÄèÎØÛ", but the
>> mbstowcs kept returning -1, until I added:
>>
>> if (setlocale(LC_ALL, "en_US.UTF-8") == NULL) {
>>
>
> What is the output of `locale` on your machine?
>
en_US.UTF-8
>> But how does one know which locale to use? From my quick read of the
>> mbstowcs man page it seems a locale needs to be set first. I also tried
>> the man page example of "Grüße!" and that worked with UTF-8.
>>
>
> It should use the locale of the system. Maybe if you have e.g. 8859-1
> set, there will be no multibyte characters, so it does not do anything.
> If we can gather that info from the errno, then we can safely skip the
> conversion as well.
>
>>> - ignore_value(virAsprintf(&ret, "%d-%.*s",
>>> - def->id, dommaxlen, def->name));
>>> + if (mbstowcs(wshortname, def->name, VIR_DOMAIN_SHORT_NAME_MAX)
>>> == (size_t) -1) {
>>> + virReportError(VIR_ERR_INVALID_ARG, "%s",
>>> + _("Cannot convert domain name to wide
>>> character string"));
>>> + return NULL;
>>> + }
>>> +
>>> + len = wcstombs(NULL, wshortname, 0);
>>> + if (len == (size_t) -1)
>>> + return NULL;
>>>
>>> + if (VIR_ALLOC_N(shortname, len + 1) < 0)
>>> + return NULL;
>>> +
>>> + if (wcstombs(shortname, wshortname, len) == (size_t) -1) {
>>> + virReportError(VIR_ERR_INVALID_ARG, "%s",
>>> + _("Cannot convert domain name from wide
>>> character string"));
>>> + goto cleanup;
>>> + }
>>> +
>>> + ignore_value(virAsprintf(&ret, "%d-%s", def->id, def->name));
>>
>> You go through all this trouble and still write def->name! I didn't
>> realize that at first either - kept wondering why the whole damn name
>> was being printed!
>>
>
> What the fsck have I sent?!?!?
>
Yeah well I only saw it after spending more than a few minutes messing
around with the code.
> I see what I did wrong, interesting. So I ran the tests with
> VIR_TEST_DEBUG=1 and I've seen some truncation not happening and I (by
> mistake) though that new truncation *is* happening now, so I re-ran with
> VIR_TEST_REGENERATE_OUTPUT=1. And it fixed the issue because there was
> no more truncation happening.
Ahhh... If I run the test directly:
VIR_TEST_DEBUG=1 ./run tests/qemuxml2argvtest
then things work as (mostly) expected as long as locale is set via a
virGettextInitialize in virDomainObjGetShortName; however, if I run via:
VIR_TEST_DEBUG=1 make -C tests check TESTS=qemuxml2argvtest
then I get the mbtowcs failure util I explicitly set the locale to
en_US.UTF-8 in virDomainObjGetShortName.
It's very odd/strange...
Since I only was messing with pcie-expander-bus-test I can also use
VIR_TEST_RANGE=565 in order to see just that output...
>
> Anyway, thanks for seeing that, that's what the reviews are for ;) v2 on
> the way.
I see v2 hit the list - I'll look at that...
John
More information about the libvir-list
mailing list