[libvirt] [PATCH v2 3/4] virDomainChrGetDomainPtrsInternal: Return an integer
Peter Krempa
pkrempa at redhat.com
Thu Jun 2 13:05:33 UTC 2016
On Thu, Jun 02, 2016 at 13:58:52 +0200, Michal Privoznik wrote:
> On 02.06.2016 13:36, Peter Krempa wrote:
> > On Thu, Jun 02, 2016 at 12:42:52 +0200, Michal Privoznik wrote:
> >> There's this problem on the recent gcc-6.1:
> >>
> >> In file included from conf/domain_conf.c:37:0:
> >> conf/domain_conf.c: In function 'virDomainChrPreAlloc':
> >> conf/domain_conf.c:14109:35: error: potential null pointer dereference [-Werror=null-dereference]
> >> return VIR_REALLOC_N(*arrPtr, *cntPtr + 1);
> >> ^~
> >> ./util/viralloc.h:158:73: note: in definition of macro 'VIR_REALLOC_N'
> >> # define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count), \
> >> ^~~~~
> >> conf/domain_conf.c: In function 'virDomainChrRemove':
> >> conf/domain_conf.c:14133:21: error: potential null pointer dereference [-Werror=null-dereference]
> >> for (i = 0; i < *cntPtr; i++) {
> >> ^~~~~~~
> >>
> >> GCC basically fails to see, that the
> >> virDomainChrGetDomainPtrsInternal will never actually return NULL
> >> because it's never called over a domain char device with _LAST
> >> type. But to make it shut up, lets turn this function into
> >> returning an integer and check in the callers if a zero value
> >> value was returned.
> >>
> >> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> >> ---
> >> src/conf/domain_conf.c | 27 +++++++++++++++++----------
> >> 1 file changed, 17 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> >> index 568c699..2efe0a3 100644
> >> --- a/src/conf/domain_conf.c
> >> +++ b/src/conf/domain_conf.c
> >> @@ -14038,7 +14038,7 @@ virDomainChrFind(virDomainDefPtr def,
> >>
> >> /* Return the address within vmdef to be modified when working with a
> >> * chrdefptr of the given type. */
> >> -static void
> >> +static int ATTRIBUTE_RETURN_CHECK
> >> virDomainChrGetDomainPtrsInternal(virDomainDefPtr vmdef,
> >> virDomainChrDeviceType type,
> >> virDomainChrDefPtr ***arrPtr,
> >> @@ -14070,6 +14070,8 @@ virDomainChrGetDomainPtrsInternal(virDomainDefPtr vmdef,
> >> *cntPtr = NULL;
> >> break;
> >> }
> >> +
> >> + return (*arrPtr && *cntPtr) ? 0 : -1;
> >
> > This doesn't set any error. The VIR_DOMAIN_CHR_DEVICE_TYPE_LAST case
> > should do so and possibly return -1 right away to avoid the ternary.
>
> Well, I'm sort of puzzled here. The reason why gcc thinks we might deref
> NULL is that at the input of this function a chardev with a type other
> than enumerated in the switch occurred. In which case we don't set any
> of the passed arguments and thus effectively defer NULL later in the
> code. This is obviously incorrect as our parser guarantees chardev type
> within range as expected here.
>
> Anyway, if I went by your approach, compiler would think that for
> CHR_DEVICE_TYPE_YET_UNKNOWN we leave the pointers untouched and return 0
> and deref NULL. The same compiler which checks all enum members are
> enumerated in the switch and therefore there can't be any
> CHR_DEVICE_TYPE_YET_UNKNOWN. Le sigh.
I think you could do something along:
*arrPtr = NULL;
*cntPtr = NULL;
switch (type) {
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
*arrPtr = &vmdef->parallels;
*cntPtr = &vmdef->nparallels;
return 0;
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
*arrPtr = &vmdef->serials;
*cntPtr = &vmdef->nserials;
return 0;
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
*arrPtr = &vmdef->consoles;
*cntPtr = &vmdef->nconsoles;
return 0;
case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
*arrPtr = &vmdef->channels;
*cntPtr = &vmdef->nchannels;
return 0;
case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
break;
}
virReportError(VIR_..., "it's broken");
return -1;
... to basically create a 'default' case outside of the switch.
Peter
More information about the libvir-list
mailing list