diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index e859a965524f08..0aacc735294e64 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -469,7 +469,7 @@ static void uc_list(char *name, size_t name_len) } // Special cases - int len = 4; + size_t len = 4; if (a & EX_BANG) { msg_putchar('!'); len--; @@ -491,7 +491,7 @@ static void uc_list(char *name, size_t name_len) } msg_outtrans_attr(cmd->uc_name, HL_ATTR(HLF_D)); - len = (int)strlen(cmd->uc_name) + 4; + len = strlen(cmd->uc_name) + 4; do { msg_putchar(' '); @@ -500,7 +500,7 @@ static void uc_list(char *name, size_t name_len) // "over" is how much longer the name is than the column width for // the name, we'll try to align what comes after. - const int over = len - 22; + const int64_t over = (int64_t)len - 22; len = 0; // Arguments @@ -524,20 +524,22 @@ static void uc_list(char *name, size_t name_len) do { IObuff[len++] = ' '; - } while (len < 5 - over); + } while ((int64_t)len < 5 - over); // Address / Range if (a & (EX_RANGE | EX_COUNT)) { if (a & EX_COUNT) { // -count=N - snprintf(IObuff + len, IOSIZE, "%" PRId64 "c", cmd->uc_def); - len += (int)strlen(IObuff + len); + int rc = snprintf(IObuff + len, IOSIZE - len, "%" PRId64 "c", cmd->uc_def); + assert(rc > 0); + len += (size_t)rc; } else if (a & EX_DFLALL) { IObuff[len++] = '%'; } else if (cmd->uc_def >= 0) { // -range=N - snprintf(IObuff + len, IOSIZE, "%" PRId64 "", cmd->uc_def); - len += (int)strlen(IObuff + len); + int rc = snprintf(IObuff + len, IOSIZE - len, "%" PRId64 "", cmd->uc_def); + assert(rc > 0); + len += (size_t)rc; } else { IObuff[len++] = '.'; } @@ -545,32 +547,34 @@ static void uc_list(char *name, size_t name_len) do { IObuff[len++] = ' '; - } while (len < 8 - over); + } while ((int64_t)len < 8 - over); // Address Type for (j = 0; addr_type_complete[j].expand != ADDR_NONE; j++) { if (addr_type_complete[j].expand != ADDR_LINES && addr_type_complete[j].expand == cmd->uc_addr_type) { - STRCPY(IObuff + len, addr_type_complete[j].shortname); - len += (int)strlen(IObuff + len); + int rc = snprintf(IObuff + len, IOSIZE - len, "%s", addr_type_complete[j].shortname); + assert(rc > 0); + len += (size_t)rc; break; } } do { IObuff[len++] = ' '; - } while (len < 13 - over); + } while ((int64_t)len < 13 - over); // Completion char *cmd_compl = get_command_complete(cmd->uc_compl); if (cmd_compl != NULL) { - STRCPY(IObuff + len, get_command_complete(cmd->uc_compl)); - len += (int)strlen(IObuff + len); + int rc = snprintf(IObuff + len, IOSIZE - len, "%s", get_command_complete(cmd->uc_compl)); + assert(rc > 0); + len += (size_t)rc; } do { IObuff[len++] = ' '; - } while (len < 25 - over); + } while ((int64_t)len < 25 - over); IObuff[len] = '\0'; msg_outtrans(IObuff); diff --git a/test/functional/ex_cmds/excmd_spec.lua b/test/functional/ex_cmds/excmd_spec.lua index b313d6428cccde..14cc2b83872762 100644 --- a/test/functional/ex_cmds/excmd_spec.lua +++ b/test/functional/ex_cmds/excmd_spec.lua @@ -28,6 +28,11 @@ describe('Ex cmds', function() assert_alive() end) + it('listing long user command does not crash', function() + command('execute "command" repeat("T", 255) ":"') + command('command') + end) + it(':def is an unknown command #23149', function() eq('Vim:E492: Not an editor command: def', pcall_err(command, 'def')) eq(1, funcs.exists(':d'))