Fossil SCM

Fix another possible memory leak in a corner case. Add more tests. Improve comments on the new Find structure.

mistachkin 2014-01-14 13:25 UTC th1UnsetVar
Commit 9b3b1d0714b1bd04c1b846878bc7b017ddbc1ed6
2 files changed +21 -8 +20
+21 -8
--- src/th.c
+++ src/th.c
@@ -1050,10 +1050,26 @@
10501050
*pnInner = nInner;
10511051
*pisGlobal = isGlobal;
10521052
return TH_OK;
10531053
}
10541054
1055
+/*
1056
+** The Find structure is used to return extra information to callers of the
1057
+** thFindValue function. The fields within it are populated by thFindValue
1058
+** as soon as the necessary information is available. Callers should zero
1059
+** out the structure prior to calling thFindValue and then check each field
1060
+** of interest upon return.
1061
+*/
1062
+
1063
+struct Find {
1064
+ Th_HashEntry *pValueEntry; /* Pointer to the scalar or array hash entry */
1065
+ Th_HashEntry *pElemEntry; /* Pointer to the element hash entry, if any */
1066
+ const char *zElem; /* Name of array element, if applicable */
1067
+ int nElem; /* Length of array element name, if applicable */
1068
+};
1069
+typedef struct Find Find;
1070
+
10551071
/*
10561072
** Input string (zVar, nVar) contains a variable name. This function locates
10571073
** the Th_Variable structure associated with the named variable. The
10581074
** variable name may be a global or local scalar or array variable
10591075
**
@@ -1063,17 +1079,10 @@
10631079
**
10641080
** If the arrayok argument is false and the named variable is an array,
10651081
** an error is left in the interpreter result and NULL returned. If
10661082
** arrayok is true an array name is Ok.
10671083
*/
1068
-struct Find {
1069
- Th_HashEntry *pValueEntry;
1070
- Th_HashEntry *pElemEntry;
1071
- const char *zElem;
1072
- int nElem;
1073
-};
1074
-typedef struct Find Find;
10751084
10761085
static Th_Variable *thFindValue(
10771086
Th_Interp *interp,
10781087
const char *zVar, /* Pointer to variable name */
10791088
int nVar, /* Number of bytes at nVar */
@@ -1310,11 +1319,11 @@
13101319
assert( pValue );
13111320
if( thFreeVariable(pEntry, (void *)interp) ){
13121321
if( find.zElem ){
13131322
Th_Variable *pValue2 = find.pValueEntry->pData;
13141323
Th_HashFind(interp, pValue2->pHash, find.zElem, find.nElem, -1);
1315
- }else{
1324
+ }else if( pEntry->pData ){
13161325
Th_Free(interp, pEntry->pData);
13171326
pEntry->pData = 0;
13181327
}
13191328
}else{
13201329
if( pValue->zData ){
@@ -1324,10 +1333,14 @@
13241333
if( pValue->pHash ){
13251334
Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp);
13261335
Th_HashDelete(interp, pValue->pHash);
13271336
pValue->pHash = 0;
13281337
}
1338
+ if( find.zElem ){
1339
+ Th_Variable *pValue2 = find.pValueEntry->pData;
1340
+ Th_HashFind(interp, pValue2->pHash, find.zElem, find.nElem, -1);
1341
+ }
13291342
}
13301343
if( !find.zElem ){
13311344
thFindValue(interp, zVar, nVar, -1, 1, 1, 0);
13321345
}
13331346
return rc;
13341347
--- src/th.c
+++ src/th.c
@@ -1050,10 +1050,26 @@
1050 *pnInner = nInner;
1051 *pisGlobal = isGlobal;
1052 return TH_OK;
1053 }
1054
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1055 /*
1056 ** Input string (zVar, nVar) contains a variable name. This function locates
1057 ** the Th_Variable structure associated with the named variable. The
1058 ** variable name may be a global or local scalar or array variable
1059 **
@@ -1063,17 +1079,10 @@
1063 **
1064 ** If the arrayok argument is false and the named variable is an array,
1065 ** an error is left in the interpreter result and NULL returned. If
1066 ** arrayok is true an array name is Ok.
1067 */
1068 struct Find {
1069 Th_HashEntry *pValueEntry;
1070 Th_HashEntry *pElemEntry;
1071 const char *zElem;
1072 int nElem;
1073 };
1074 typedef struct Find Find;
1075
1076 static Th_Variable *thFindValue(
1077 Th_Interp *interp,
1078 const char *zVar, /* Pointer to variable name */
1079 int nVar, /* Number of bytes at nVar */
@@ -1310,11 +1319,11 @@
1310 assert( pValue );
1311 if( thFreeVariable(pEntry, (void *)interp) ){
1312 if( find.zElem ){
1313 Th_Variable *pValue2 = find.pValueEntry->pData;
1314 Th_HashFind(interp, pValue2->pHash, find.zElem, find.nElem, -1);
1315 }else{
1316 Th_Free(interp, pEntry->pData);
1317 pEntry->pData = 0;
1318 }
1319 }else{
1320 if( pValue->zData ){
@@ -1324,10 +1333,14 @@
1324 if( pValue->pHash ){
1325 Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp);
1326 Th_HashDelete(interp, pValue->pHash);
1327 pValue->pHash = 0;
1328 }
 
 
 
 
1329 }
1330 if( !find.zElem ){
1331 thFindValue(interp, zVar, nVar, -1, 1, 1, 0);
1332 }
1333 return rc;
1334
--- src/th.c
+++ src/th.c
@@ -1050,10 +1050,26 @@
1050 *pnInner = nInner;
1051 *pisGlobal = isGlobal;
1052 return TH_OK;
1053 }
1054
1055 /*
1056 ** The Find structure is used to return extra information to callers of the
1057 ** thFindValue function. The fields within it are populated by thFindValue
1058 ** as soon as the necessary information is available. Callers should zero
1059 ** out the structure prior to calling thFindValue and then check each field
1060 ** of interest upon return.
1061 */
1062
1063 struct Find {
1064 Th_HashEntry *pValueEntry; /* Pointer to the scalar or array hash entry */
1065 Th_HashEntry *pElemEntry; /* Pointer to the element hash entry, if any */
1066 const char *zElem; /* Name of array element, if applicable */
1067 int nElem; /* Length of array element name, if applicable */
1068 };
1069 typedef struct Find Find;
1070
1071 /*
1072 ** Input string (zVar, nVar) contains a variable name. This function locates
1073 ** the Th_Variable structure associated with the named variable. The
1074 ** variable name may be a global or local scalar or array variable
1075 **
@@ -1063,17 +1079,10 @@
1079 **
1080 ** If the arrayok argument is false and the named variable is an array,
1081 ** an error is left in the interpreter result and NULL returned. If
1082 ** arrayok is true an array name is Ok.
1083 */
 
 
 
 
 
 
 
1084
1085 static Th_Variable *thFindValue(
1086 Th_Interp *interp,
1087 const char *zVar, /* Pointer to variable name */
1088 int nVar, /* Number of bytes at nVar */
@@ -1310,11 +1319,11 @@
1319 assert( pValue );
1320 if( thFreeVariable(pEntry, (void *)interp) ){
1321 if( find.zElem ){
1322 Th_Variable *pValue2 = find.pValueEntry->pData;
1323 Th_HashFind(interp, pValue2->pHash, find.zElem, find.nElem, -1);
1324 }else if( pEntry->pData ){
1325 Th_Free(interp, pEntry->pData);
1326 pEntry->pData = 0;
1327 }
1328 }else{
1329 if( pValue->zData ){
@@ -1324,10 +1333,14 @@
1333 if( pValue->pHash ){
1334 Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp);
1335 Th_HashDelete(interp, pValue->pHash);
1336 pValue->pHash = 0;
1337 }
1338 if( find.zElem ){
1339 Th_Variable *pValue2 = find.pValueEntry->pData;
1340 Th_HashFind(interp, pValue2->pHash, find.zElem, find.nElem, -1);
1341 }
1342 }
1343 if( !find.zElem ){
1344 thFindValue(interp, zVar, nVar, -1, 1, 1, 0);
1345 }
1346 return rc;
1347
--- test/th1.test
+++ test/th1.test
@@ -187,5 +187,25 @@
187187
188188
###############################################################################
189189
190190
fossil test-th-eval "set gv 1; proc p {} {upvar 1 gv lv; unset lv}; p; unset gv"
191191
test th1-unset-4 {$RESULT eq {TH_ERROR: no such variable: gv}}
192
+
193
+###############################################################################
194
+
195
+fossil test-th-eval "set gv 1; upvar 0 gv gv2; info exists gv2"
196
+test th1-unset-5 {$RESULT eq {1}}
197
+
198
+###############################################################################
199
+
200
+fossil test-th-eval "set gv 1; upvar 0 gv gv2; unset gv; unset gv2"
201
+test th1-unset-6 {$RESULT eq {TH_ERROR: no such variable: gv2}}
202
+
203
+###############################################################################
204
+
205
+fossil test-th-eval "set gv 1; upvar 0 gv gv2(1); unset gv; unset gv2(1)"
206
+test th1-unset-7 {$RESULT eq {TH_ERROR: no such variable: gv2(1)}}
207
+
208
+###############################################################################
209
+
210
+fossil test-th-eval "set gv(1) 1; upvar 0 gv(1) gv2; unset gv(1); unset gv2"
211
+test th1-unset-8 {$RESULT eq {TH_ERROR: no such variable: gv2}}
192212
--- test/th1.test
+++ test/th1.test
@@ -187,5 +187,25 @@
187
188 ###############################################################################
189
190 fossil test-th-eval "set gv 1; proc p {} {upvar 1 gv lv; unset lv}; p; unset gv"
191 test th1-unset-4 {$RESULT eq {TH_ERROR: no such variable: gv}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
--- test/th1.test
+++ test/th1.test
@@ -187,5 +187,25 @@
187
188 ###############################################################################
189
190 fossil test-th-eval "set gv 1; proc p {} {upvar 1 gv lv; unset lv}; p; unset gv"
191 test th1-unset-4 {$RESULT eq {TH_ERROR: no such variable: gv}}
192
193 ###############################################################################
194
195 fossil test-th-eval "set gv 1; upvar 0 gv gv2; info exists gv2"
196 test th1-unset-5 {$RESULT eq {1}}
197
198 ###############################################################################
199
200 fossil test-th-eval "set gv 1; upvar 0 gv gv2; unset gv; unset gv2"
201 test th1-unset-6 {$RESULT eq {TH_ERROR: no such variable: gv2}}
202
203 ###############################################################################
204
205 fossil test-th-eval "set gv 1; upvar 0 gv gv2(1); unset gv; unset gv2(1)"
206 test th1-unset-7 {$RESULT eq {TH_ERROR: no such variable: gv2(1)}}
207
208 ###############################################################################
209
210 fossil test-th-eval "set gv(1) 1; upvar 0 gv(1) gv2; unset gv(1); unset gv2"
211 test th1-unset-8 {$RESULT eq {TH_ERROR: no such variable: gv2}}
212

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button