Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#4332 closed Bug (fixed)

countRange/countArray exception

Reported by: jerwied Owned by: jordan
Priority: Normal Milestone: 2.32
Component: libtransmission Version: 2.31
Severity: Normal Keywords:


The countRange() function is broken when fed with begin==end.

Attached is a rewrite of this function which works with my local installation.

IMHO there is also an assertion error, the function countArray counts all bits in a bitfield, even if not all bits are used, so the condition for assert() is wrong.

Attachments (1)

transmission-bitfield.diff (3.0 KB) - added by jerwied 10 years ago.
rewrite of countRange()-function

Download all attachments as: .zip

Change History (8)

Changed 10 years ago by jerwied

rewrite of countRange()-function

comment:1 Changed 10 years ago by jordan

I appreciate the patch, but I don't understand its goal. The arguments named "begin" and "end" to follow the typical C convention of [begin...end) so begin should never point to the same space as end. Also, "make check" fails in utils-test when this patch is applied. What use case is this patch trying to address?

comment:2 Changed 10 years ago by jordan

  • Version changed from 2.31+ to 2.31

comment:3 Changed 10 years ago by jordan

Also, I think bitMaskHigh in that diff should be:

bitMaskHigh[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0xf, 0x7, 0x3, 0x1 };

comment:4 Changed 10 years ago by jerwied

For me it is not true that begin<end, attached is a backtrace of a crashed (asserted) transmission-daemon:

#4  0x0807dfa2 in countRange (b=0x8112828, begin=716, end=716) at bitfield.c:71
#5  0x0807e1e7 in tr_bitfieldCountRange (b=0x8112828, begin=716, end=716) at bitfield.c:127
#6  0x08081099 in tr_cpMissingBytesInPiece (cp=0x8112824, piece=179) at completion.c:217
#7  0x0808a069 in tr_peerMgrGetDesiredAvailable (tor=0x8112640) at peer-mgr.c:2595
#8  0x0806659c in tr_torrentStat (tor=0x8112640) at torrent.c:1189

When doing a 'print *cp' frame #6, I get:

$2 = {tor = 0xb6a3dc08, blockBitfield = {bits = 0x86e03b0 "", alloc_count = 90, bit_count = 717, true_count = 26, have_all_hint = false, have_none_hint = true},

sizeWhenDoneLazy = 11733940, sizeWhenDoneIsDirty = false, haveValidLazy = 396212, haveValidIsDirty = false, sizeNow = 412596}

The last piece (torrent has 180 pieces) has a size of 2996, which is smaller than tor->blockSize, and thus tr_torGetPieceBlockRange will return a first/last of 716/716, which is passed along to countRange, giving an assertion.

After doing some further digging it seems like the above assertion is only triggered when accessing the daemon via transmission-remote (or webfrontend).

Finally I just added another initial check to countRange():

    if( begin == end )
        return 0;

That seems to fix my problems in the debugging build, don't know if that's 100% correct, though.

Just forget about the patch, I've been looking in the wrong direction.

comment:5 Changed 10 years ago by jordan

  • Milestone changed from None Set to 2.32
  • Status changed from new to assigned

aha! Thanks for the backtrace.

Looks like the root cause is an off-by-one in completion.c:217. tr_torGetPieceBlockRange() returns a range of [first...last], and we pass that through unchanged to bitfield's [begin...end)... :|

comment:6 Changed 10 years ago by jordan

  • Resolution set to fixed
  • Status changed from assigned to closed

This should be fixed by r12515. If the problem persists, please reopen the ticket.

Thanks again for reporting this!

comment:7 Changed 10 years ago by jordan

followup: maybe this wasn't such a good fix -- see #4336

Note: See TracTickets for help on using tickets.