@@ -4,7 +4,7 @@ import * as constants from './constants';
44import * as dbg from './debugger' ;
55import { Log as logger } from './logger' ;
66import { PghhError , EvaluationError , unnullify } from './error' ;
7- import { Configuration } from './configuration' ;
7+ import { Configuration , VsCodeSettings } from './configuration' ;
88
99export interface AliasInfo {
1010 /* Declared type */
@@ -579,6 +579,15 @@ export class ExecContext {
579579 }
580580}
581581
582+ function clampContainerLength ( size : number ) {
583+ const max = VsCodeSettings . getMaxContainerLength ( ) ;
584+ return max < size ? max : size ;
585+ }
586+
587+ function getMaxContainerLength ( ) {
588+ return VsCodeSettings . getMaxContainerLength ( ) ;
589+ }
590+
582591/**
583592 * Special value for frameId used by ephemeral variables:
584593 * they do not need to evaluate anything.
@@ -3897,8 +3906,8 @@ export class ListNodeVariable extends NodeVariable {
38973906 logger . warn ( 'failed to obtain list size for %s' , this . name ) ;
38983907 return ;
38993908 }
3900- /* TODO: add size check */
3901- return length ;
3909+
3910+ return clampContainerLength ( length ) ;
39023911 }
39033912
39043913 async getListElements ( ) {
@@ -3921,12 +3930,6 @@ export class ListNodeVariable extends NodeVariable {
39213930
39223931
39233932export class ArraySpecialMember extends RealVariable {
3924- /**
3925- * Prevent errors/bugs if there was garbage after
3926- * length expression evaluation.
3927- */
3928- static plausibleMaxLength = 1024 ;
3929-
39303933 /**
39313934 * Expression to evaluate to obtain array length.
39323935 * Appended to target struct from right.
@@ -4000,9 +4003,7 @@ export class ArraySpecialMember extends RealVariable {
40004003 }
40014004
40024005 /* Yes, we may have garbage, but what if the array is that huge? */
4003- if ( ArraySpecialMember . plausibleMaxLength < length ) {
4004- length = ArraySpecialMember . plausibleMaxLength ;
4005- }
4006+ length = clampContainerLength ( length ) ;
40064007
40074008 const parent = unnullify ( this . parent , 'this.parent' ) ;
40084009 const memberExpr = `((${ parent . type } )${ parent . getPointer ( ) } )->${ this . info . memberName } ` ;
@@ -4063,11 +4064,14 @@ class BitmapSetSpecialMember extends NodeVariable {
40634064 }
40644065
40654066 const n = Number ( nwords . value ) ;
4067+
40664068 /*
4067- * For 64-bit system even 20 is large number: 10 * 64 = 640.
4068- * Human will not be able to handle such amount of data.
4069+ * For 64-bit system even 50 is large number: 50 * 64 = 3200.
4070+ * But actually this is *potential* size, so can we allow such
4071+ * large value - in reality it can contain only 1 element, just
4072+ * in last word, but this acts like a pretty good correctness check.
40694073 */
4070- const maxNWords = 10 ;
4074+ const maxNWords = 50 ;
40714075 if ( Number . isNaN ( n ) || maxNWords <= n ) {
40724076 return false ;
40734077 }
@@ -4165,6 +4169,7 @@ class BitmapSetSpecialMember extends NodeVariable {
41654169
41664170 let number = - 1 ;
41674171 const numbers = [ ] ;
4172+ const maxLength = getMaxContainerLength ( ) ;
41684173 do {
41694174 const expression = `bms_next_member((Bitmapset *)${ this . getPointer ( ) } , ${ number } )` ;
41704175 try {
@@ -4188,7 +4193,7 @@ class BitmapSetSpecialMember extends NodeVariable {
41884193 }
41894194
41904195 numbers . push ( number ) ;
4191- } while ( number >= 0 ) ;
4196+ } while ( number >= 0 && numbers . length < maxLength ) ;
41924197
41934198 return numbers ;
41944199 }
@@ -4216,6 +4221,7 @@ class BitmapSetSpecialMember extends NodeVariable {
42164221 }
42174222
42184223 const expression = `bms_first_member((Bitmapset *)${ e . result } )` ;
4224+ const maxLength = getMaxContainerLength ( ) ;
42194225 let number = - 1 ;
42204226 const numbers = [ ] ;
42214227 do {
@@ -4232,7 +4238,7 @@ class BitmapSetSpecialMember extends NodeVariable {
42324238 }
42334239
42344240 numbers . push ( number ) ;
4235- } while ( number >= 0 ) ;
4241+ } while ( number >= 0 && numbers . length < maxLength ) ;
42364242
42374243 await this . pfree ( e . result ) ;
42384244
@@ -4843,7 +4849,6 @@ class HTABElementsMember extends Variable {
48434849 */
48444850 try {
48454851 await this . evaluateVoid ( `hash_seq_term((HASH_SEQ_STATUS *)${ hashSeqStatus } )` ) ;
4846-
48474852 } catch ( err ) {
48484853 if ( ! ( err instanceof EvaluationError ) ) {
48494854 throw err ;
@@ -4879,6 +4884,7 @@ class HTABElementsMember extends Variable {
48794884 return ;
48804885 }
48814886
4887+ const maxLength = getMaxContainerLength ( ) ;
48824888 let entry ;
48834889 while ( ( entry = await this . getNextHashEntry ( hashSeqStatus ) ) ) {
48844890 let result ;
@@ -4897,13 +4903,14 @@ class HTABElementsMember extends Variable {
48974903 return undefined ;
48984904 }
48994905
4906+ let variable ;
49004907 try {
4901- const variable = await Variable . create ( {
4908+ variable = await Variable . create ( {
49024909 ...result ,
4903- name : `${ variables . length } ` ,
4910+ name : `[ ${ variables . length } ] ` ,
49044911 value : result . result ,
4912+ memoryReference : result . memoryReference ,
49054913 } , this . frameId , this . context , this ) ;
4906- variables . push ( variable ) ;
49074914 } catch ( error ) {
49084915 if ( error instanceof EvaluationError ) {
49094916 await this . finalizeHashSeqStatus ( hashSeqStatus ) ;
@@ -4912,6 +4919,16 @@ class HTABElementsMember extends Variable {
49124919
49134920 throw error ;
49144921 }
4922+
4923+ variables . push ( variable ) ;
4924+ if ( maxLength < variables . length ) {
4925+ /*
4926+ * If we terminate iteration before iteration is completed,
4927+ * we have to call finalizer function
4928+ */
4929+ await this . finalizeHashSeqStatus ( hashSeqStatus ) ;
4930+ break ;
4931+ }
49154932 }
49164933
49174934 await this . pfree ( hashSeqStatus ) ;
@@ -5008,15 +5025,16 @@ class SimplehashElementsMember extends Variable {
50085025 hashTable ) ;
50095026 this . hashTable = hashTable ;
50105027 }
5028+
5029+ protected async getDescription ( ) {
5030+ return '' ;
5031+ }
50115032
5012- async getTreeItem ( ) : Promise < vscode . TreeItem > {
5013- /* Show only '$elements$' */
5014- return {
5015- label : '$elements$' ,
5016- collapsibleState : vscode . TreeItemCollapsibleState . Collapsed ,
5017- } ;
5033+ protected isExpandable ( ) {
5034+ return true ;
50185035 }
50195036
5037+ /* TODO: no need to cache these */
50205038 /*
50215039 * Cached identifier names for function and types
50225040 */
@@ -5087,7 +5105,7 @@ class SimplehashElementsMember extends Variable {
50875105 return iteratorPtr ;
50885106 }
50895107
5090- async iterate ( iterator : string , current : number ) {
5108+ async iterate ( iterator : string , index : number ) {
50915109 const iterFunction = this . getIteratorFunction ( ) ;
50925110 const hashTableType = `(${ this . getHashTableType ( ) } *) ${ this . hashTable . getPointer ( ) } ` ;
50935111 const iteratorArg = `(${ this . getIteratorType ( ) } *) ${ iterator } ` ;
@@ -5113,8 +5131,9 @@ class SimplehashElementsMember extends Variable {
51135131 try {
51145132 return await Variable . create ( {
51155133 ...result ,
5116- name : `${ current } ` ,
5134+ name : `[ ${ index } ] ` ,
51175135 value : result . result ,
5136+ memoryReference : result . memoryReference ,
51185137 } , this . frameId , this . context , this ) ;
51195138 } catch ( err ) {
51205139 if ( ! ( err instanceof EvaluationError ) ) {
@@ -5149,10 +5168,12 @@ class SimplehashElementsMember extends Variable {
51495168 return ;
51505169 }
51515170
5171+ const maxLength = getMaxContainerLength ( ) ;
51525172 const variables = [ ] ;
51535173 let id = 0 ;
51545174 let variable ;
5155- while ( ( variable = await this . iterate ( iterator , id ) ) ) {
5175+ while ( variables . length < maxLength
5176+ && ( variable = await this . iterate ( iterator , id ) ) ) {
51565177 ++ id ;
51575178 variables . push ( variable ) ;
51585179 }
@@ -5179,7 +5200,7 @@ class FlagsMemberVariable extends RealVariable {
51795200 * debug symbols (i.e. for gdb use '-g3' level).
51805201 *
51815202 * But even if we know numeric value of enum member and have the same
5182- * endianess we still have to evaluate all expressions in debugger, because
5203+ * endianness we still have to evaluate all expressions in debugger, because
51835204 * 1) due to another major pg version numeric values can change
51845205 * 2) we can debug coredump collected from another machine, so we should not
51855206 * assume this PC is binary compatible with one that is debugged
0 commit comments