Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug in BlistList for two ranges that could lead to wrong results #3689

Merged
merged 1 commit into from
Oct 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/blister.c
Original file line number Diff line number Diff line change
Expand Up @@ -1286,9 +1286,9 @@ static Obj FuncUNITE_BLIST_LIST(Obj self, Obj list, Obj blist, Obj sub)
UInt bit; /* one bit of block */
Int lenList; /* logical length of the list */
const Obj * ptrSub; /* pointer to the sublist */
UInt lenSub; /* logical length of sublist */
UInt i, j, k = 0, l; /* loop variables */
long s, t; /* elements of a range */
Int lenSub; /* logical length of sublist */
Int i, j, k, l; /* loop variables */
Int s, t; /* elements of a range */
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s, t were just of type long, so in 64 bit mode, with compilers where long is only 32 bit (basically anywhere except some Microsoft / Windows compilers), there could be overflow here. I didn't add tests for that, though.


RequireSmallList("UniteBlistList", list);
RequireBlist("UniteBlistList", blist);
Expand All @@ -1313,19 +1313,22 @@ static Obj FuncUNITE_BLIST_LIST(Obj self, Obj list, Obj blist, Obj sub)
/* get the bounds of the subset with respect to the boolean list */
s = INT_INTOBJ( GET_ELM_RANGE( list, 1 ) );
t = INT_INTOBJ( GET_ELM_RANGE( sub, 1 ) );
if ( s <= t ) i = t - s + 1;
else i = 1;

if ( i + lenSub - 1 <= lenList ) j = i + lenSub - 1;
else j = lenList;
// compute bounds
i = t - s;
j = lenSub + i;
if (i < 0)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that it is crucial to compute i and j before capping the bounds; clearly the previous two lines do not commute; yet in the old code, they were in the wrong order.

i = 0;
if (j > lenList)
j = lenList;

/* set the corresponding entries to 'true' */
for ( k = i; k <= j && (k-1)%BIPEB != 0; k++ )
ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);
for ( ; k+BIPEB <= j; k += BIPEB )
ptrBlist[(k-1)/BIPEB] = ~(UInt)0;
for ( ; k <= j; k++ )
ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);
for ( k = i; k < j && k%BIPEB != 0; k++ )
ptrBlist[k/BIPEB] |= (1UL << k%BIPEB);
for ( ; k+BIPEB < j; k += BIPEB )
ptrBlist[k/BIPEB] = ~(UInt)0;
for ( ; k < j; k++ )
ptrBlist[k/BIPEB] |= (1UL << k%BIPEB);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that k-1 changed to k by adjusting the bounds. I hope the optimizer would have produced identical results in both cases; but the result is certainly slightly easier to read.


}

Expand Down
20 changes: 20 additions & 0 deletions tst/testinstall/kernel/blister.tst
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,35 @@ gap> List(l, IsSSortedList);
gap> List(l, SizeBlist);
[ 1, 1, 2, 2 ]

#
# FuncBLIST_LIST
#
gap> BlistList(fail, fail);
Error, BlistList: <list> must be a small list (not the value 'fail')
gap> BlistList([1,2,3], fail);
Error, BlistList: <sub> must be a small list (not the value 'fail')
gap> BlistList([1,2,3], [1,3]);
[ true, false, true ]

# ranges with increment 1
gap> BlistList([0..3], [-3..-1]);
[ false, false, false, false ]
gap> BlistList([0..3], [-3..1]);
[ true, true, false, false ]
gap> BlistList([0..3], [-3..6]);
[ true, true, true, true ]
gap> BlistList([0..3], [0..1]);
[ true, true, false, false ]
gap> BlistList([0..3], [0..6]);
[ true, true, true, true ]
gap> BlistList([0..3], [2..6]);
[ false, false, true, true ]
gap> BlistList([0..3], [4..6]);
[ false, false, false, false ]

#
# FuncLIST_BLIST
#
gap> ListBlist(fail, fail);
Error, ListBlist: <list> must be a small list (not the value 'fail')
gap> ListBlist([1,2,3], fail);
Expand Down