To: vim_dev@googlegroups.com Subject: Patch 8.1.0736 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0736 Problem: Code for Blob not sufficiently tested. Solution: Add more tests. Fix uncovered crash. Add test_null_blob(). Files: src/testdir/test_blob.vim, src/testdir/test_assign.vim, src/eval.c, src/testdir/test_eval_stuff.vim, src/testdir/test_lambda.vim, runtime/doc/eval.txt, src/evalfunc.c, src/blob.c, src/testdir/test49.vim *** ../vim-8.1.0735/src/testdir/test_blob.vim 2019-01-12 22:47:01.264088074 +0100 --- src/testdir/test_blob.vim 2019-01-13 15:05:51.133009938 +0100 *************** *** 21,26 **** --- 21,32 ---- call assert_equal(0xDE, get(b, 0)) call assert_equal(0xEF, get(b, 3)) call assert_fails('let x = get(b, 4)') + + call assert_fails('let b = 0z1', 'E973:') + call assert_fails('let b = 0z1x', 'E973:') + call assert_fails('let b = 0z12345', 'E973:') + + call assert_equal(0z, test_null_blob()) endfunc " assignment to a blob *************** *** 32,37 **** --- 38,82 ---- let bcopy = b[:] call assert_equal(b, bcopy) call assert_false(b is bcopy) + + let b = 0zDEADBEEF + let b2 = b + call assert_true(b is b2) + let b[:] = 0z11223344 + call assert_equal(0z11223344, b) + call assert_equal(0z11223344, b2) + call assert_true(b is b2) + + let b = 0zDEADBEEF + let b[3:] = 0z66 + call assert_equal(0zDEADBE66, b) + let b[:1] = 0z8899 + call assert_equal(0z8899BE66, b) + + call assert_fails('let b[2:3] = 0z112233', 'E972:') + call assert_fails('let b[2:3] = 0z11', 'E972:') + call assert_fails('let b[3:2] = 0z', 'E979:') + + let b = 0zDEADBEEF + let b += 0z99 + call assert_equal(0zDEADBEEF99, b) + + call assert_fails('let b .= 0z33', 'E734:') + call assert_fails('let b .= "xx"', 'E734:') + call assert_fails('let b += "xx"', 'E734:') + call assert_fails('let b[1:1] .= 0z55', 'E734:') + endfunc + + func Test_blob_get_range() + let b = 0z0011223344 + call assert_equal(0z2233, b[2:3]) + call assert_equal(0z223344, b[2:-1]) + call assert_equal(0z00, b[0:-5]) + call assert_equal(0z, b[0:-11]) + call assert_equal(0z44, b[-1:]) + call assert_equal(0z0011223344, b[:]) + call assert_equal(0z0011223344, b[:-1]) + call assert_equal(0z, b[5:6]) endfunc func Test_blob_to_string() *************** *** 44,51 **** --- 89,100 ---- func Test_blob_compare() let b1 = 0z0011 let b2 = 0z1100 + let b3 = 0z001122 + call assert_true(b1 == b1) call assert_false(b1 == b2) + call assert_false(b1 == b3) call assert_true(b1 != b2) + call assert_true(b1 != b3) call assert_true(b1 == 0z0011) call assert_false(b1 is b2) *************** *** 65,71 **** let b[1] = 0x11 let b[2] = 0x22 call assert_equal(0z001122, b) ! call assert_fails('let b[4] = 0x33') endfunc func Test_blob_for_loop() --- 114,120 ---- let b[1] = 0x11 let b[2] = 0x22 call assert_equal(0z001122, b) ! call assert_fails('let b[4] = 0x33', 'E979:') endfunc func Test_blob_for_loop() *************** *** 177,179 **** --- 226,240 ---- call assert_equal('[222,173,190,239]', json_encode(0zDEADBEEF)) call assert_equal('[]', json_encode(0z)) endfunc + + func Test_blob_lock() + let b = 0z112233 + lockvar b + call assert_fails('let b = 0z44', 'E741:') + unlockvar b + let b = 0z44 + endfunc + + func Test_blob_sort() + call assert_fails('call sort([1.0, 0z11], "f")', 'E975:') + endfunc *** ../vim-8.1.0735/src/testdir/test_assign.vim 2017-10-02 19:28:43.000000000 +0200 --- src/testdir/test_assign.vim 2019-01-13 14:41:55.754889476 +0100 *************** *** 23,33 **** let &t_k1 = old_t_k1 endif ! call assert_fails('let x = &t_xx', 'E15') let &t_xx = "yes" call assert_equal("yes", &t_xx) let &t_xx = "" ! call assert_fails('let x = &t_xx', 'E15') endfunc func Test_let_option_error() --- 23,33 ---- let &t_k1 = old_t_k1 endif ! call assert_fails('let x = &t_xx', 'E113') let &t_xx = "yes" call assert_equal("yes", &t_xx) let &t_xx = "" ! call assert_fails('let x = &t_xx', 'E113') endfunc func Test_let_option_error() *************** *** 43,45 **** --- 43,53 ---- call assert_equal("vert:|", &fillchars) let &fillchars = _w endfunc + + func Test_let_errors() + let s = 'abcd' + call assert_fails('let s[1] = 5', 'E689:') + + let l = [1, 2, 3] + call assert_fails('let l[:] = 5', 'E709:') + endfunc *** ../vim-8.1.0735/src/eval.c 2019-01-12 22:47:01.260088089 +0100 --- src/eval.c 2019-01-13 14:43:52.298118934 +0100 *************** *** 1983,1991 **** } if (rettv != NULL && !(rettv->v_type == VAR_LIST ! || rettv->vval.v_list != NULL) && !(rettv->v_type == VAR_BLOB ! || rettv->vval.v_blob != NULL)) { if (!quiet) EMSG(_("E709: [:] requires a List or Blob value")); --- 1983,1991 ---- } if (rettv != NULL && !(rettv->v_type == VAR_LIST ! && rettv->vval.v_list != NULL) && !(rettv->v_type == VAR_BLOB ! && rettv->vval.v_blob != NULL)) { if (!quiet) EMSG(_("E709: [:] requires a List or Blob value")); *************** *** 2109,2114 **** --- 2109,2116 ---- } else if (lp->ll_tv->v_type == VAR_BLOB) { + long bloblen = blob_len(lp->ll_tv->vval.v_blob); + /* * Get the number and item for the only or first index of the List. */ *************** *** 2120,2135 **** clear_tv(&var1); if (lp->ll_n1 < 0 ! || lp->ll_n1 > blob_len(lp->ll_tv->vval.v_blob)) { if (!quiet) ! EMSGN(_(e_listidx), lp->ll_n1); return NULL; } if (lp->ll_range && !lp->ll_empty2) { lp->ll_n2 = (long)tv_get_number(&var2); clear_tv(&var2); } lp->ll_blob = lp->ll_tv->vval.v_blob; lp->ll_tv = NULL; --- 2122,2147 ---- clear_tv(&var1); if (lp->ll_n1 < 0 ! || lp->ll_n1 > bloblen ! || (lp->ll_range && lp->ll_n1 == bloblen)) { if (!quiet) ! EMSGN(_(e_blobidx), lp->ll_n1); ! clear_tv(&var2); return NULL; } if (lp->ll_range && !lp->ll_empty2) { lp->ll_n2 = (long)tv_get_number(&var2); clear_tv(&var2); + if (lp->ll_n2 < 0 + || lp->ll_n2 >= bloblen + || lp->ll_n2 < lp->ll_n1) + { + if (!quiet) + EMSGN(_(e_blobidx), lp->ll_n2); + return NULL; + } } lp->ll_blob = lp->ll_tv->vval.v_blob; lp->ll_tv = NULL; *************** *** 2241,2246 **** --- 2253,2259 ---- if (lp->ll_blob != NULL) { int error = FALSE, val; + if (op != NULL && *op != '=') { EMSG2(_(e_letwrong), op); *************** *** 2249,2265 **** if (lp->ll_range && rettv->v_type == VAR_BLOB) { ! int i; ! if (blob_len(rettv->vval.v_blob) != blob_len(lp->ll_blob)) { ! EMSG(_("E972: Blob value has more items than target")); return; } ! for (i = lp->ll_n1; i <= lp->ll_n2; i++) ! blob_set(lp->ll_blob, i, ! blob_get(rettv->vval.v_blob, i)); } else { --- 2262,2284 ---- if (lp->ll_range && rettv->v_type == VAR_BLOB) { ! int il, ir; ! if (lp->ll_empty2) ! lp->ll_n2 = blob_len(lp->ll_blob) - 1; ! ! if (lp->ll_n2 - lp->ll_n1 + 1 != blob_len(rettv->vval.v_blob)) { ! EMSG(_("E972: Blob value does not have the right number of bytes")); return; } + if (lp->ll_empty2) + lp->ll_n2 = blob_len(lp->ll_blob); ! ir = 0; ! for (il = lp->ll_n1; il <= lp->ll_n2; il++) ! blob_set(lp->ll_blob, il, ! blob_get(rettv->vval.v_blob, ir++)); } else { *************** *** 2278,2285 **** if (lp->ll_n1 == gap->ga_len) ++gap->ga_len; } ! else ! EMSG(_(e_invrange)); } } } --- 2297,2303 ---- if (lp->ll_n1 == gap->ga_len) ++gap->ga_len; } ! // error for invalid range was already given in get_lval() } } } *************** *** 2312,2318 **** else if (lp->ll_range) { listitem_T *ll_li = lp->ll_li; ! int ll_n1 = lp->ll_n1; /* * Check whether any of the list items is locked --- 2330,2336 ---- else if (lp->ll_range) { listitem_T *ll_li = lp->ll_li; ! int ll_n1 = lp->ll_n1; /* * Check whether any of the list items is locked *************** *** 3354,3359 **** --- 3372,3379 ---- { int ret; char_u *p; + int did_emsg_before = did_emsg; + int called_emsg_before = called_emsg; p = skipwhite(arg); ret = eval1(&p, rettv, evaluate); *************** *** 3364,3372 **** /* * Report the invalid expression unless the expression evaluation has * been cancelled due to an aborting error, an interrupt, or an ! * exception. */ ! if (!aborting()) EMSG2(_(e_invexpr2), arg); ret = FAIL; } --- 3384,3394 ---- /* * Report the invalid expression unless the expression evaluation has * been cancelled due to an aborting error, an interrupt, or an ! * exception, or we already gave a more specific error. ! * Also check called_emsg for when using assert_fails(). */ ! if (!aborting() && did_emsg == did_emsg_before ! && called_emsg == called_emsg_before) EMSG2(_(e_invexpr2), arg); ret = FAIL; } *************** *** 4195,4201 **** { if (!vim_isxdigit(bp[1])) { ! EMSG(_("E973: Blob literal should have an even number of hex characters'")); vim_free(blob); ret = FAIL; break; --- 4217,4223 ---- { if (!vim_isxdigit(bp[1])) { ! EMSG(_("E973: Blob literal should have an even number of hex characters")); vim_free(blob); ret = FAIL; break; *************** *** 4632,4638 **** len = blob_len(rettv->vval.v_blob); if (range) { ! // The resulting variable is a substring. If the indexes // are out of range the result is empty. if (n1 < 0) { --- 4654,4660 ---- len = blob_len(rettv->vval.v_blob); if (range) { ! // The resulting variable is a sub-blob. If the indexes // are out of range the result is empty. if (n1 < 0) { *************** *** 8336,8341 **** --- 8358,8364 ---- int atstart = TRUE; char_u numbuf[NUMBUFLEN]; int did_emsg_before = did_emsg; + int called_emsg_before = called_emsg; if (eap->skip) ++emsg_skip; *************** *** 8353,8359 **** * has been cancelled due to an aborting error, an interrupt, or an * exception. */ ! if (!aborting() && did_emsg == did_emsg_before) EMSG2(_(e_invexpr2), p); need_clr_eos = FALSE; break; --- 8376,8383 ---- * has been cancelled due to an aborting error, an interrupt, or an * exception. */ ! if (!aborting() && did_emsg == did_emsg_before ! && called_emsg == called_emsg_before) EMSG2(_(e_invexpr2), p); need_clr_eos = FALSE; break; *** ../vim-8.1.0735/src/testdir/test_eval_stuff.vim 2018-12-05 18:43:24.489493117 +0100 --- src/testdir/test_eval_stuff.vim 2019-01-13 14:14:28.258162292 +0100 *************** *** 63,65 **** --- 63,71 ---- call assert_fails("let v:oldfiles=''", 'E963:') call assert_equal(v_o, v:oldfiles) endfunc + + func Test_for_invalid() + call assert_fails("for x in 99", 'E714:') + call assert_fails("for x in 'asdf'", 'E714:') + call assert_fails("for x in {'a': 9}", 'E714:') + endfunc *** ../vim-8.1.0735/src/testdir/test_lambda.vim 2019-01-09 23:00:57.997176121 +0100 --- src/testdir/test_lambda.vim 2019-01-13 14:40:58.051266393 +0100 *************** *** 49,55 **** function Test_lambda_fails() call assert_equal(3, {a, b -> a + b}(1, 2)) ! call assert_fails('echo {a, a -> a + a}(1, 2)', 'E15:') call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:') endfunc --- 49,55 ---- function Test_lambda_fails() call assert_equal(3, {a, b -> a + b}(1, 2)) ! call assert_fails('echo {a, a -> a + a}(1, 2)', 'E853:') call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:') endfunc *************** *** 169,175 **** let l:D = s:NewCounter2() call assert_equal(1, l:C()) ! call assert_fails(':call l:D()', 'E15:') " E121: then E15: call assert_equal(2, l:C()) endfunc --- 169,175 ---- let l:D = s:NewCounter2() call assert_equal(1, l:C()) ! call assert_fails(':call l:D()', 'E121:') call assert_equal(2, l:C()) endfunc *** ../vim-8.1.0735/runtime/doc/eval.txt 2019-01-12 22:47:01.256088105 +0100 --- runtime/doc/eval.txt 2019-01-13 14:49:35.755795777 +0100 *************** *** 2507,2528 **** term_setrestore({buf}, {command}) none set command to restore terminal term_setsize({buf}, {rows}, {cols}) none set the size of a terminal ! term_start({cmd}, {options}) Job open a terminal window and run a job term_wait({buf} [, {time}]) Number wait for screen to be updated test_alloc_fail({id}, {countdown}, {repeat}) none make memory allocation fail test_autochdir() none enable 'autochdir' during startup ! test_feedinput() none add key sequence to input buffer test_garbagecollect_now() none free memory right now for testing test_ignore_error({expr}) none ignore a specific error test_null_channel() Channel null value for testing test_null_dict() Dict null value for testing test_null_job() Job null value for testing test_null_list() List null value for testing test_null_partial() Funcref null value for testing test_null_string() String null value for testing ! test_option_not_set({name}) none reset flag indicating option was set ! test_override({expr}, {val}) none test with Vim internal overrides test_scrollbar({which}, {value}, {dragging}) none scroll in the GUI for testing test_settime({expr}) none set current time for testing --- 2520,2542 ---- term_setrestore({buf}, {command}) none set command to restore terminal term_setsize({buf}, {rows}, {cols}) none set the size of a terminal ! term_start({cmd}, {options}) Number open a terminal window and run a job term_wait({buf} [, {time}]) Number wait for screen to be updated test_alloc_fail({id}, {countdown}, {repeat}) none make memory allocation fail test_autochdir() none enable 'autochdir' during startup ! test_feedinput({string}) none add key sequence to input buffer test_garbagecollect_now() none free memory right now for testing test_ignore_error({expr}) none ignore a specific error + test_null_blob() Blob null value for testing test_null_channel() Channel null value for testing test_null_dict() Dict null value for testing test_null_job() Job null value for testing test_null_list() List null value for testing test_null_partial() Funcref null value for testing test_null_string() String null value for testing ! test_option_not_set({name}) none reset flag indicating option was set ! test_override({expr}, {val}) none test with Vim internal overrides test_scrollbar({which}, {value}, {dragging}) none scroll in the GUI for testing test_settime({expr}) none set current time for testing *************** *** 9310,9334 **** When the {expr} is the string "RESET" then the list of ignored errors is made empty. test_null_channel() *test_null_channel()* ! Return a Channel that is null. Only useful for testing. {only available when compiled with the +channel feature} test_null_dict() *test_null_dict()* ! Return a Dict that is null. Only useful for testing. test_null_job() *test_null_job()* ! Return a Job that is null. Only useful for testing. {only available when compiled with the +job feature} test_null_list() *test_null_list()* ! Return a List that is null. Only useful for testing. test_null_partial() *test_null_partial()* ! Return a Partial that is null. Only useful for testing. test_null_string() *test_null_string()* ! Return a String that is null. Only useful for testing. test_option_not_set({name}) *test_option_not_set()* Reset the flag that indicates option {name} was set. Thus it --- 9339,9366 ---- When the {expr} is the string "RESET" then the list of ignored errors is made empty. + test_null_blob() *test_null_blob()* + Return a |Blob| that is null. Only useful for testing. + test_null_channel() *test_null_channel()* ! Return a |Channel| that is null. Only useful for testing. {only available when compiled with the +channel feature} test_null_dict() *test_null_dict()* ! Return a |Dict| that is null. Only useful for testing. test_null_job() *test_null_job()* ! Return a |Job| that is null. Only useful for testing. {only available when compiled with the +job feature} test_null_list() *test_null_list()* ! Return a |List| that is null. Only useful for testing. test_null_partial() *test_null_partial()* ! Return a |Partial| that is null. Only useful for testing. test_null_string() *test_null_string()* ! Return a |String| that is null. Only useful for testing. test_option_not_set({name}) *test_option_not_set()* Reset the flag that indicates option {name} was set. Thus it *** ../vim-8.1.0735/src/evalfunc.c 2019-01-12 22:47:01.260088089 +0100 --- src/evalfunc.c 2019-01-13 14:51:50.650868801 +0100 *************** *** 429,434 **** --- 429,435 ---- static void f_test_override(typval_T *argvars, typval_T *rettv); static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv); static void f_test_ignore_error(typval_T *argvars, typval_T *rettv); + static void f_test_null_blob(typval_T *argvars, typval_T *rettv); #ifdef FEAT_JOB_CHANNEL static void f_test_null_channel(typval_T *argvars, typval_T *rettv); #endif *************** *** 950,955 **** --- 951,957 ---- {"test_feedinput", 1, 1, f_test_feedinput}, {"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now}, {"test_ignore_error", 1, 1, f_test_ignore_error}, + {"test_null_blob", 0, 0, f_test_null_blob}, #ifdef FEAT_JOB_CHANNEL {"test_null_channel", 0, 0, f_test_null_channel}, #endif *************** *** 13902,13907 **** --- 13904,13916 ---- ignore_error_for_testing(tv_get_string(&argvars[0])); } + static void + f_test_null_blob(typval_T *argvars UNUSED, typval_T *rettv) + { + rettv->v_type = VAR_BLOB; + rettv->vval.v_blob = NULL; + } + #ifdef FEAT_JOB_CHANNEL static void f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv) *** ../vim-8.1.0735/src/blob.c 2019-01-12 22:47:01.256088105 +0100 --- src/blob.c 2019-01-13 14:55:40.973274231 +0100 *************** *** 114,126 **** blob_T *b1, blob_T *b2) { ! int i; ! if (b1 == NULL || b2 == NULL) ! return FALSE; if (b1 == b2) return TRUE; ! if (blob_len(b1) != blob_len(b2)) return FALSE; for (i = 0; i < b1->bv_ga.ga_len; i++) --- 114,129 ---- blob_T *b1, blob_T *b2) { ! int i; ! int len1 = blob_len(b1); ! int len2 = blob_len(b2); ! // empty and NULL are considered the same ! if (len1 == 0 && len2 == 0) ! return TRUE; if (b1 == b2) return TRUE; ! if (len1 != len2) return FALSE; for (i = 0; i < b1->bv_ga.ga_len; i++) *** ../vim-8.1.0735/src/testdir/test49.vim 2019-01-09 23:00:57.997176121 +0100 --- src/testdir/test49.vim 2019-01-13 15:11:40.054554337 +0100 *************** *** 1,6 **** " Vim script language tests " Author: Servatius Brandt ! " Last Change: 2019 Jan 09 "------------------------------------------------------------------------------- " Test environment {{{1 --- 1,6 ---- " Vim script language tests " Author: Servatius Brandt ! " Last Change: 2019 Jan 13 "------------------------------------------------------------------------------- " Test environment {{{1 *************** *** 3694,3700 **** if ExtraVim(msgfile) try Xpath 4194304 " X: 4194304 ! let x = novar " error E121/E15; exception: E121 catch /E15:/ " should not catch Xpath 8388608 " X: 0 endtry --- 3694,3700 ---- if ExtraVim(msgfile) try Xpath 4194304 " X: 4194304 ! let x = novar " error E121; exception: E121 catch /E15:/ " should not catch Xpath 8388608 " X: 0 endtry *************** *** 3702,3708 **** endif Xpath 33554432 " X: 33554432 ! if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression") Xpath 67108864 " X: 0 endif --- 3702,3708 ---- endif Xpath 33554432 " X: 33554432 ! if !MESSAGES('E121', "Undefined variable") Xpath 67108864 " X: 0 endif *** ../vim-8.1.0735/src/version.c 2019-01-12 22:47:01.264088074 +0100 --- src/version.c 2019-01-13 14:14:53.593982643 +0100 *************** *** 797,798 **** --- 797,800 ---- { /* Add new patch number below this line */ + /**/ + 736, /**/ -- hundred-and-one symptoms of being an internet addict: 182. You may not know what is happening in the world, but you know every bit of net-gossip there is. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///