Bug 19412 - xdrmem_setpos: UB when pos is large
Summary: xdrmem_setpos: UB when pos is large
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: network (show other bugs)
Version: 2.22
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-28 14:10 UTC by Alexander Cherepanov
Modified: 2015-12-28 14:10 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Cherepanov 2015-12-28 14:10:34 UTC
It seems xdrmem_setpos tries to defend against out-of-bounds values of the pos argument:

 174 static bool_t
 175 xdrmem_setpos (XDR *xdrs, u_int pos)
 176 {
 177   caddr_t newaddr = xdrs->x_base + pos;
 178   caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
 179   size_t handy = lastaddr - newaddr;
 180 
 181   if (newaddr > lastaddr
 182       || newaddr < xdrs->x_base
 183       || handy != (u_int) handy)
 184     return FALSE;
 185 
 186   xdrs->x_private = newaddr;
 187   xdrs->x_handy = (u_int) handy;
 188   return TRUE;
 189 }

https://sourceware.org/git/?p=glibc.git;a=blob;f=sunrpc/xdr_mem.c;h=8b9858959476ad8bee7f7eaa7250c516beda55b4;hb=HEAD#l174

This code is invalid C. The sum "xdrs->x_base + pos" (line 177) is undefined by the C standard when the result doesn't point into the same array. Then, checks for pointer wrapping like "newaddr < xdrs->x_base" (line 182) are already "miscompiled" by clang and, I guess, could be expected to be broken by gcc in the future.

Similar to pr19391.