Mercurial > vim
comparison src/vim9class.c @ 31447:8cb31f7ac9e2 v9.0.1056
patch 9.0.1056: leaking memory when disassembling an object method
Commit: https://github.com/vim/vim/commit/eb53350c02f620305e931ffd2ac611cc2b1a0ce9
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Dec 14 15:06:11 2022 +0000
patch 9.0.1056: leaking memory when disassembling an object method
Problem: Leaking memory when disassembling an object method.
Solution: Free the typval of the class.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 14 Dec 2022 16:15:04 +0100 |
parents | 9ae3720f9bd9 |
children | 5ef28f5ff357 |
comparison
equal
deleted
inserted
replaced
31446:a03b5695e9c5 | 31447:8cb31f7ac9e2 |
---|---|
166 expr_start = skipwhite(expr_start + 1); | 166 expr_start = skipwhite(expr_start + 1); |
167 | 167 |
168 expr_end = expr_start; | 168 expr_end = expr_start; |
169 evalarg_T evalarg; | 169 evalarg_T evalarg; |
170 fill_evalarg_from_eap(&evalarg, eap, FALSE); | 170 fill_evalarg_from_eap(&evalarg, eap, FALSE); |
171 skip_expr(&expr_end, &evalarg); | 171 skip_expr(&expr_end, NULL); |
172 | 172 |
173 if (type == NULL) | 173 if (type == NULL) |
174 { | 174 { |
175 // No type specified, use the type of the initializer. | 175 // No type specified, use the type of the initializer. |
176 typval_T tv; | 176 typval_T tv; |
253 break; | 253 break; |
254 } | 254 } |
255 } | 255 } |
256 vim_free(theline); | 256 vim_free(theline); |
257 | 257 |
258 class_T *cl = NULL; | |
258 if (success) | 259 if (success) |
259 { | 260 { |
260 class_T *cl = ALLOC_CLEAR_ONE(class_T); | 261 cl = ALLOC_CLEAR_ONE(class_T); |
261 if (cl == NULL) | 262 if (cl == NULL) |
262 goto cleanup; | 263 goto cleanup; |
263 cl->class_refcount = 1; | 264 cl->class_refcount = 1; |
264 cl->class_name = vim_strnsave(arg, name_end - arg); | 265 cl->class_name = vim_strnsave(arg, name_end - arg); |
265 | 266 |
267 cl->class_obj_member_count = objmembers.ga_len; | 268 cl->class_obj_member_count = objmembers.ga_len; |
268 cl->class_obj_members = objmembers.ga_len == 0 ? NULL | 269 cl->class_obj_members = objmembers.ga_len == 0 ? NULL |
269 : ALLOC_MULT(objmember_T, objmembers.ga_len); | 270 : ALLOC_MULT(objmember_T, objmembers.ga_len); |
270 if (cl->class_name == NULL | 271 if (cl->class_name == NULL |
271 || (objmembers.ga_len > 0 && cl->class_obj_members == NULL)) | 272 || (objmembers.ga_len > 0 && cl->class_obj_members == NULL)) |
272 { | |
273 vim_free(cl->class_name); | |
274 vim_free(cl->class_obj_members); | |
275 vim_free(cl); | |
276 goto cleanup; | 273 goto cleanup; |
277 } | |
278 mch_memmove(cl->class_obj_members, objmembers.ga_data, | 274 mch_memmove(cl->class_obj_members, objmembers.ga_data, |
279 sizeof(objmember_T) * objmembers.ga_len); | 275 sizeof(objmember_T) * objmembers.ga_len); |
280 vim_free(objmembers.ga_data); | 276 vim_free(objmembers.ga_data); |
281 | 277 |
282 int have_new = FALSE; | 278 int have_new = FALSE; |
336 } | 332 } |
337 | 333 |
338 cl->class_obj_method_count = objmethods.ga_len; | 334 cl->class_obj_method_count = objmethods.ga_len; |
339 cl->class_obj_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len); | 335 cl->class_obj_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len); |
340 if (cl->class_obj_methods == NULL) | 336 if (cl->class_obj_methods == NULL) |
341 { | |
342 vim_free(cl->class_name); | |
343 vim_free(cl->class_obj_members); | |
344 vim_free(cl->class_obj_methods); | |
345 vim_free(cl); | |
346 goto cleanup; | 337 goto cleanup; |
347 } | |
348 mch_memmove(cl->class_obj_methods, objmethods.ga_data, | 338 mch_memmove(cl->class_obj_methods, objmethods.ga_data, |
349 sizeof(ufunc_T *) * objmethods.ga_len); | 339 sizeof(ufunc_T *) * objmethods.ga_len); |
350 vim_free(objmethods.ga_data); | 340 vim_free(objmethods.ga_data); |
351 | 341 |
352 // Set the class pointer on all the object methods. | 342 // Set the class pointer on all the object methods. |
380 NULL, &tv, FALSE, ASSIGN_DECL, 0); | 370 NULL, &tv, FALSE, ASSIGN_DECL, 0); |
381 return; | 371 return; |
382 } | 372 } |
383 | 373 |
384 cleanup: | 374 cleanup: |
375 if (cl != NULL) | |
376 { | |
377 vim_free(cl->class_name); | |
378 vim_free(cl->class_obj_members); | |
379 vim_free(cl->class_obj_methods); | |
380 vim_free(cl); | |
381 } | |
382 | |
385 for (int i = 0; i < objmembers.ga_len; ++i) | 383 for (int i = 0; i < objmembers.ga_len; ++i) |
386 { | 384 { |
387 objmember_T *m = ((objmember_T *)objmembers.ga_data) + i; | 385 objmember_T *m = ((objmember_T *)objmembers.ga_data) + i; |
388 vim_free(m->om_name); | 386 vim_free(m->om_name); |
389 vim_free(m->om_init); | 387 vim_free(m->om_init); |
589 typval_T tv; | 587 typval_T tv; |
590 tv.v_type = VAR_UNKNOWN; | 588 tv.v_type = VAR_UNKNOWN; |
591 if (eval_variable(name, len, 0, &tv, NULL, EVAL_VAR_NOAUTOLOAD) == FAIL) | 589 if (eval_variable(name, len, 0, &tv, NULL, EVAL_VAR_NOAUTOLOAD) == FAIL) |
592 return NULL; | 590 return NULL; |
593 if (tv.v_type != VAR_CLASS && tv.v_type != VAR_OBJECT) | 591 if (tv.v_type != VAR_CLASS && tv.v_type != VAR_OBJECT) |
594 { | 592 goto fail_after_eval; |
595 clear_tv(&tv); | |
596 return NULL; | |
597 } | |
598 | 593 |
599 class_T *cl = tv.v_type == VAR_CLASS ? tv.vval.v_class | 594 class_T *cl = tv.v_type == VAR_CLASS ? tv.vval.v_class |
600 : tv.vval.v_object->obj_class; | 595 : tv.vval.v_object->obj_class; |
601 if (cl == NULL) | 596 if (cl == NULL) |
602 return NULL; | 597 goto fail_after_eval; |
603 char_u *fname = name_end + 1; | 598 char_u *fname = name_end + 1; |
604 char_u *fname_end = find_name_end(fname, NULL, NULL, FNE_CHECK_START); | 599 char_u *fname_end = find_name_end(fname, NULL, NULL, FNE_CHECK_START); |
605 if (fname_end == fname) | 600 if (fname_end == fname) |
606 return NULL; | 601 goto fail_after_eval; |
607 len = fname_end - fname; | 602 len = fname_end - fname; |
608 | 603 |
609 for (int i = 0; i < cl->class_obj_method_count; ++i) | 604 for (int i = 0; i < cl->class_obj_method_count; ++i) |
610 { | 605 { |
611 ufunc_T *fp = cl->class_obj_methods[i]; | 606 ufunc_T *fp = cl->class_obj_methods[i]; |
612 // Use a separate pointer to avoid that ASAN complains about | 607 // Use a separate pointer to avoid that ASAN complains about |
613 // uf_name[] only being 4 characters. | 608 // uf_name[] only being 4 characters. |
614 char_u *ufname = (char_u *)fp->uf_name; | 609 char_u *ufname = (char_u *)fp->uf_name; |
615 if (STRNCMP(fname, ufname, len) == 0 && ufname[len] == NUL) | 610 if (STRNCMP(fname, ufname, len) == 0 && ufname[len] == NUL) |
611 { | |
612 clear_tv(&tv); | |
616 return fp; | 613 return fp; |
617 } | 614 } |
618 | 615 } |
616 | |
617 fail_after_eval: | |
618 clear_tv(&tv); | |
619 return NULL; | 619 return NULL; |
620 } | 620 } |
621 | 621 |
622 /* | 622 /* |
623 * Make a copy of an object. | 623 * Make a copy of an object. |