Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfbb1dae

Browse files
committed
Fix incorrect addition, subtraction, and overflow checking in new
inet operators.
1 parent77bb65d commitfbb1dae

File tree

4 files changed

+374
-263
lines changed

4 files changed

+374
-263
lines changed

‎src/backend/utils/adt/network.c

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
*PostgreSQL type definitions for the INET and CIDR types.
33
*
4-
*$PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.64 2006/02/1103:32:39 momjian Exp $
4+
*$PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.65 2006/02/1120:39:58 tgl Exp $
55
*
66
*Jon Postel RIP 16 Oct 1998
77
*/
@@ -27,7 +27,7 @@ static int32 network_cmp_internal(inet *a1, inet *a2);
2727
staticintbitncmp(void*l,void*r,intn);
2828
staticbooladdressOK(unsignedchar*a,intbits,intfamily);
2929
staticintip_addrsize(inet*inetptr);
30-
staticDatuminternal_inetpl(inet*ip,int64iarg);
30+
staticinet*internal_inetpl(inet*ip,int64addend);
3131

3232
/*
3333
*Access macros.
@@ -1292,8 +1292,7 @@ inetand(PG_FUNCTION_ARGS)
12921292
if (ip_family(ip)!=ip_family(ip2))
12931293
ereport(ERROR,
12941294
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1295-
errmsg("mismatch in address family (%d) != (%d)",
1296-
ip_family(ip),ip_family(ip2))));
1295+
errmsg("cannot AND inet values of different sizes")));
12971296
else
12981297
{
12991298
intnb=ip_addrsize(ip);
@@ -1327,8 +1326,7 @@ inetor(PG_FUNCTION_ARGS)
13271326
if (ip_family(ip)!=ip_family(ip2))
13281327
ereport(ERROR,
13291328
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1330-
errmsg("mismatch in address family (%d) != (%d)",
1331-
ip_family(ip),ip_family(ip2))));
1329+
errmsg("cannot OR inet values of different sizes")));
13321330
else
13331331
{
13341332
intnb=ip_addrsize(ip);
@@ -1350,8 +1348,8 @@ inetor(PG_FUNCTION_ARGS)
13501348
}
13511349

13521350

1353-
staticDatum
1354-
internal_inetpl(inet*ip,int64plus)
1351+
staticinet*
1352+
internal_inetpl(inet*ip,int64addend)
13551353
{
13561354
inet*dst;
13571355

@@ -1365,15 +1363,31 @@ internal_inetpl(inet *ip, int64 plus)
13651363

13661364
while (nb-->0)
13671365
{
1368-
pdst[nb]=carry=pip[nb]+plus+carry;
1369-
plus /=0x100;/* process next byte */
1370-
carry /=0x100;/* remove low byte */
1371-
/* Overflow on high byte? */
1372-
if (nb==0&& (plus!=0||carry!=0))
1373-
ereport(ERROR,
1374-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1375-
errmsg("result out of range")));
1366+
carry=pip[nb]+ (int) (addend&0xFF)+carry;
1367+
pdst[nb]= (unsignedchar) (carry&0xFF);
1368+
carry >>=8;
1369+
/*
1370+
* We have to be careful about right-shifting addend because
1371+
* right-shift isn't portable for negative values, while
1372+
* simply dividing by 256 doesn't work (the standard rounding
1373+
* is in the wrong direction, besides which there may be machines
1374+
* out there that round the wrong way). So, explicitly clear
1375+
* the low-order byte to remove any doubt about the correct
1376+
* result of the division, and then divide rather than shift.
1377+
*/
1378+
addend &= ~((int64)0xFF);
1379+
addend /=0x100;
13761380
}
1381+
/*
1382+
* At this point we should have addend and carry both zero if
1383+
* original addend was >= 0, or addend -1 and carry 1 if original
1384+
* addend was < 0. Anything else means overflow.
1385+
*/
1386+
if (!((addend==0&&carry==0)||
1387+
(addend==-1&&carry==1)))
1388+
ereport(ERROR,
1389+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1390+
errmsg("result out of range")));
13771391
}
13781392
ip_bits(dst)=ip_bits(ip);
13791393

@@ -1382,27 +1396,27 @@ internal_inetpl(inet *ip, int64 plus)
13821396
((char*)ip_addr(dst)- (char*)VARDATA(dst))+
13831397
ip_addrsize(dst);
13841398

1385-
PG_RETURN_INET_P(dst);
1399+
returndst;
13861400
}
13871401

13881402

13891403
Datum
13901404
inetpl(PG_FUNCTION_ARGS)
13911405
{
13921406
inet*ip=PG_GETARG_INET_P(0);
1393-
int64plus=PG_GETARG_INT64(1);
1407+
int64addend=PG_GETARG_INT64(1);
13941408

1395-
returninternal_inetpl(ip,plus);
1409+
PG_RETURN_INET_P(internal_inetpl(ip,addend));
13961410
}
13971411

13981412

13991413
Datum
14001414
inetmi_int8(PG_FUNCTION_ARGS)
14011415
{
14021416
inet*ip=PG_GETARG_INET_P(0);
1403-
int64plus=PG_GETARG_INT64(1);
1417+
int64addend=PG_GETARG_INT64(1);
14041418

1405-
returninternal_inetpl(ip,-plus);
1419+
PG_RETURN_INET_P(internal_inetpl(ip,-addend));
14061420
}
14071421

14081422

@@ -1416,42 +1430,53 @@ inetmi(PG_FUNCTION_ARGS)
14161430
if (ip_family(ip)!=ip_family(ip2))
14171431
ereport(ERROR,
14181432
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1419-
errmsg("mismatch in address family (%d) != (%d)",
1420-
ip_family(ip),ip_family(ip2))));
1433+
errmsg("cannot subtract inet values of different sizes")));
14211434
else
14221435
{
1436+
/*
1437+
* We form the difference using the traditional complement,
1438+
* increment, and add rule, with the increment part being handled
1439+
* by starting the carry off at 1. If you don't think integer
1440+
* arithmetic is done in two's complement, too bad.
1441+
*/
14231442
intnb=ip_addrsize(ip);
14241443
intbyte=0;
14251444
unsignedchar*pip=ip_addr(ip);
14261445
unsignedchar*pip2=ip_addr(ip2);
1446+
intcarry=1;
14271447

14281448
while (nb-->0)
14291449
{
1430-
/*
1431-
*Error if overflow on last byte. This test is tricky
1432-
*because if the subtraction == 128 and res is negative, or
1433-
*if subtraction == -128 and res is positive, the result
1434-
*would still fit in int64.
1435-
*/
1436-
if (byte+1==sizeof(int64)&&
1437-
(pip[nb]-pip2[nb] >=128+ (res<0)||
1438-
pip[nb]-pip2[nb] <=-128- (res>0)))
1439-
ereport(ERROR,
1440-
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1441-
errmsg("result out of range")));
1442-
if (byte >=sizeof(int64))
1450+
intlobyte;
1451+
1452+
carry=pip[nb]+ (~pip2[nb]&0xFF)+carry;
1453+
lobyte=carry&0xFF;
1454+
if (byte<sizeof(int64))
14431455
{
1444-
/* Error if bytes beyond int64 length differ. */
1445-
if (pip[nb]!=pip2[nb])
1456+
res |= ((int64)lobyte) << (byte*8);
1457+
}
1458+
else
1459+
{
1460+
/*
1461+
* Input wider than int64: check for overflow. All bytes
1462+
* to the left of what will fit should be 0 or 0xFF,
1463+
* depending on sign of the now-complete result.
1464+
*/
1465+
if ((res<0) ? (lobyte!=0xFF) : (lobyte!=0))
14461466
ereport(ERROR,
14471467
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
14481468
errmsg("result out of range")));
14491469
}
1450-
else
1451-
res+= (int64)(pip[nb]-pip2[nb]) << (byte*8);
1452-
1470+
carry >>=8;
14531471
byte++;
14541472
}
1473+
1474+
/*
1475+
* If input is narrower than int64, overflow is not possible, but
1476+
* we have to do proper sign extension.
1477+
*/
1478+
if (carry==0&&byte<sizeof(int64))
1479+
res |= ((int64)-1) << (byte*8);
14551480
}
14561481

14571482
PG_RETURN_INT64(res);

‎src/include/catalog/pg_proc.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.395 2006/02/1103:32:39 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.396 2006/02/1120:39:58 tgl Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2297,7 +2297,7 @@ DESCR("bitwise or");
22972297
DATA(insertOID=1675 (bitxorPGNSPPGUID12fftfi21560"1560 1560"_null__null__null_bitxor-_null_ ));
22982298
DESCR("bitwise exclusive or");
22992299
DATA(insertOID=1676 (bitnotPGNSPPGUID12fftfi11560"1560"_null__null__null_bitnot-_null_ ));
2300-
DESCR("bitwisenegation");
2300+
DESCR("bitwisenot");
23012301
DATA(insertOID=1677 (bitshiftleftPGNSPPGUID12fftfi21560"1560 23"_null__null__null_bitshiftleft-_null_ ));
23022302
DESCR("bitwise left shift");
23032303
DATA(insertOID=1678 (bitshiftrightPGNSPPGUID12fftfi21560"1560 23"_null__null__null_bitshiftright-_null_ ));
@@ -2423,28 +2423,28 @@ DATA(insert OID = 1715 ( cidrPGNSP PGUID 12 f f t f i 1 650 "869" _null_ _n
24232423
DESCR("coerce inet to cidr");
24242424

24252425
DATA(insertOID=2196 (inet_client_addrPGNSPPGUID12ffffs0869""_null__null__null_inet_client_addr-_null_ ));
2426-
DESCR("INET address of the client");
2426+
DESCR("inet address of the client");
24272427
DATA(insertOID=2197 (inet_client_portPGNSPPGUID12ffffs023""_null__null__null_inet_client_port-_null_ ));
24282428
DESCR("client's port number for this connection");
24292429
DATA(insertOID=2198 (inet_server_addrPGNSPPGUID12ffffs0869""_null__null__null_inet_server_addr-_null_ ));
2430-
DESCR("INET address of the server");
2430+
DESCR("inet address of the server");
24312431
DATA(insertOID=2199 (inet_server_portPGNSPPGUID12ffffs023""_null__null__null_inet_server_port-_null_ ));
24322432
DESCR("server's port number for this connection");
24332433

24342434
DATA(insertOID=2627 (inetnotPGNSPPGUID12fftfi1869"869"_null__null__null_inetnot-_null_ ));
2435-
DESCR("binary NOT");
2435+
DESCR("bitwise not");
24362436
DATA(insertOID=2628 (inetandPGNSPPGUID12fftfi2869"869 869"_null__null__null_inetand-_null_ ));
2437-
DESCR("binary AND");
2437+
DESCR("bitwise and");
24382438
DATA(insertOID=2629 (inetorPGNSPPGUID12fftfi2869"869 869"_null__null__null_inetor-_null_ ));
2439-
DESCR("binary OR");
2439+
DESCR("bitwise or");
24402440
DATA(insertOID=2630 (inetplPGNSPPGUID12fftfi2869"869 20"_null__null__null_inetpl-_null_ ));
2441-
DESCR("add integer toINET value");
2442-
DATA(insertOID=2631 (int8pl_inetPGNSPPGUID14fftfi2869"20 869"_null__null__null_"select $2 + $1"-_null_ ));
2443-
DESCR("add integer toINET value");
2441+
DESCR("add integer toinet value");
2442+
DATA(insertOID=2631 (int8pl_inetPGNSPPGUID14fftfi2869"20 869"_null__null__null_"select $2 + $1"-_null_ ));
2443+
DESCR("add integer toinet value");
24442444
DATA(insertOID=2632 (inetmi_int8PGNSPPGUID12fftfi2869"869 20"_null__null__null_inetmi_int8-_null_ ));
2445-
DESCR("subtract integer fromINET value");
2445+
DESCR("subtract integer frominet value");
24462446
DATA(insertOID=2633 (inetmiPGNSPPGUID12fftfi220"869 869"_null__null__null_inetmi-_null_ ));
2447-
DESCR("subtractINET values");
2447+
DESCR("subtractinet values");
24482448

24492449
DATA(insertOID=1686 (numericPGNSPPGUID12fftfi11700"25"_null__null__null_text_numeric-_null_ ));
24502450
DESCR("(internal)");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp