
( >( so what's going on here
the latest information shows that some non-numeric data is being parsed as a number ... maybe a wrong link pointer is being placed, like maybe a length field is being written as a pointer who knows
the two regions of interest seem separate for me. maybe i can ferry enough information from one to another to discern a cause
i got a reprieve i can hold them near each other a little
(Pdb) list 31 addr8 = memoryview(id).cast('Q')[0] 32 l8 = max((self.q[addr8]+self.idsize-1)//self.idsize,1) + 1 33 self.q[addr8] = self.q[0] 34 self.q[addr8+1] = l8 35 self.q[0] = addr8 36 -> self.fsck() 37 def alloc(self, data, replacing=[]): 38 self.fsck() 39 l8 = max((len(data)+self.idsize-1)//self.idsize,1) + 1 40 addr8 = 0 41 assert self.q[addr8] != 0 (Pdb) p addr8 1 (Pdb) p id b'\x01\x00\x00\x00\x00\x00\x00\x00'
so this is what was deallocated. there was an allocated region at 0x1<<3 ... i think? [.. addr8 = memoryview(id).cast('Q')[0] ...] yeah the id is an address in quadwords. now below i didn't see a region starting at 0x1 in the regions list. :/ [scrolls down] oh no wait there totally was one :D :s ok so here ummm it's working on address 1 quadwords O_O O_O O_O
(Pdb) p self.q[addr8] 11
this is after address so this should be the link. it says the next one is the region at 11<<3.
(Pdb) p l8 4
this is the calculated length of the region in quadwords
(Pdb) p addr8 1 (Pdb) p l8 4 (Pdb) p self.w[addr8*self.idsize:addr8+self.idsize+4*self.idsize] <memory at 0x7f0a3b9d9840> (Pdb) p self.w[addr8*self.idsize:addr8+self.idsize+4*self.idsize].tobytes() b'\x0b\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00k brown fox jum\x00\t'
and here's the raw data of the region. 0x0b is 11, the link to the next deallocated region. 0x4 is the length of the region in quadwords -- 32 bytes. it looks reasonable at a glance but something obviously is wrong; while trying to sleep i was wondering maybe the l8 quantity is inconsistent. another thought is maybe quadwords vs raw lengths is inconsistent, or somehow elsewise a disalignment. but usually it's been because of a logic case i left out, like how the regions list isn't updated during shrink.
the 'k brown fox jum' content looks believable. additionally, the fsck prior to the deallocation passed [ :S ]
(Pdb) down
/home/karl3/projects/rep/rep/i.py(114)fsck() -> assert l8 <= self.yq - addr8 (Pdb) list 109 passed_regions.append(region) 110 assert region[1] <= self.yq - addr8 111 addr8 += region[1] 112 else: 113 l8 = max((self.q[addr8]+self.idsize-1)//self.idsize,1) + 1 114 -> assert l8 <= self.yq - addr8 115 addr8 += l8 116 assert addr8 == self.yq 117 def shrink(self): 118 self.fsck() 119 unused = 0 (Pdb) p addr8 4
so here we are at address 4, not address 1. glancing down to `p regions` below, address 4 .. hrm ... [ ... regions.append([addr8, self.q[addr8+1]]) ... ] ... there's no address 4. 4 is the length of address 1. so this might be a bug in fsck ??? ... 0442 regions[] only contains deallocated regions. this is a branch for an allocated region. it's like the region after region 1 ...? (shouldn't that be 5?) i'm closer !!!!! ummmmmmmmmmmmmm 0444 so regions contains a region starting at 1. additionally, passed_regions is empty. [this debugging session found left open it's slightly possible it came from a different codebase slightly, but it has the passed_regions local]. passed_regions is set when processing a deallocated region >( so i don't know why addr8 is 4 ... yet ! what i can do is simulate the behavior of the function. addr8 started at 1. YAY I FOUND A BUG !!!! yay bug :D the regions are sorted in reversal, likely with intent to pop things from it like a stack. but region[0] is checked instead of popping or using region[-1]. i modified the algorithm partly and didn't sufficiently propagate the changes. this does not fully explain the condition but it's part. it shows why passed_regions is empty. 0448 here's new lines: assert regions[-1][0] >= addr8 if regions[-1][0] == addr8: 0449 so i guess that what must have happened would have been uh l8 = max((self.q[addr8]+self.idsize-1)//self.idsize,1) + 1 address 1 would have been treated as allocated, and the value considered an allocated length. (11). uhh ? but addr8 isn't 11+1=12. it's 4 :/ uhhh hehe oh but it's converted ! (Pdb) p max((11+self.idsize-1)//self.idsize,1) + 1 3 there we go. 3+1==4. so we found the bug! this was the bug!! bug tracking is hard, little tiny footprints, but they're there !
(Pdb) p self.q[addr8] 30809871133208422 (Pdb) p l8 3851233891651054 (Pdb) p regions [[11, 501], [1, 4]] (Pdb) p passed_regions []