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.