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

Reading bit value goes into an infinity loop #2766

Closed
kbth opened this issue Dec 14, 2019 · 5 comments
Closed

Reading bit value goes into an infinity loop #2766

kbth opened this issue Dec 14, 2019 · 5 comments
Assignees
Labels
bug
Milestone

Comments

@kbth
Copy link

@kbth kbth commented Dec 14, 2019

When reading a bit type value, I encountered a bug that caused an infinite loop under certain conditions.

Steps to reproduce

using (var conn = new NpgsqlConnection(connnectionString))
{
    conn.Open();

    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = @"SELECT 1::bit(100000);";

        using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
        {
            reader.Read();
            reader.GetValue(0); // infinite loop!!
        }
    }
}

The issue

BitStringHandler has the cause. In case a bit value cuts across a buffer boundary, the last byte will never read and result in an infinite loop. The buf.ReadBytesLeft property remains at 1 and the loop cannot be escaped.

do
{
var iterationEndPos = bytesLeft - Math.Min(bytesLeft, buf.ReadBytesLeft) + 1;
for (; bytesLeft > iterationEndPos; bytesLeft--)
{
// ReSharper disable ShiftExpressionRealShiftCountIsZero
var chunk = buf.ReadByte();
result[bitNo++] = (chunk & (1 << 7)) != 0;
result[bitNo++] = (chunk & (1 << 6)) != 0;
result[bitNo++] = (chunk & (1 << 5)) != 0;
result[bitNo++] = (chunk & (1 << 4)) != 0;
result[bitNo++] = (chunk & (1 << 3)) != 0;
result[bitNo++] = (chunk & (1 << 2)) != 0;
result[bitNo++] = (chunk & (1 << 1)) != 0;
result[bitNo++] = (chunk & (1 << 0)) != 0;
}
} while (bytesLeft > 1);

Above example is terrible, but our application is facing same problem. It reads 16-bit column values, and cuts across a buffer boundary depending on the data state.

If I set CommandBehavior to default, it works. but we use Dapper, and Dapper's Query method internally sets CommandBehavior.SequentialAccess link.

Further technical details

Npgsql version: 4.1.2
PostgreSQL version: 9.6
Operating system: Windows 10

@roji

This comment has been minimized.

Copy link
Member

@roji roji commented Dec 14, 2019

@YohDeadfall do you want to take this?

@YohDeadfall

This comment has been minimized.

Copy link
Member

@YohDeadfall YohDeadfall commented Dec 14, 2019

Would like, but without a rush. Am out of the city till tomorrow (:

@YohDeadfall YohDeadfall self-assigned this Dec 14, 2019
@YohDeadfall YohDeadfall added the bug label Jan 19, 2020
@YohDeadfall YohDeadfall added this to the 4.1.3 milestone Jan 19, 2020
@roji roji closed this in ef5ccd7 Jan 24, 2020
roji added a commit that referenced this issue Jan 24, 2020
Fixes #2766

(cherry picked from commit ef5ccd7)
@mintsoft

This comment has been minimized.

Copy link

@mintsoft mintsoft commented Jan 25, 2020

@YohDeadfall

This comment has been minimized.

Copy link
Member

@YohDeadfall YohDeadfall commented Jan 25, 2020

The reason is Debug.Assert added by Shay, but code works (: The only disadvantage is bad performance which should be fixed by #2808.

@mintsoft

This comment has been minimized.

Copy link

@mintsoft mintsoft commented Jan 25, 2020

@YohDeadfall Aha that makes sense, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.