0

I am trying to write a sample program which can parse a string and store its host name and port number separately.

After I identify number of characters to write for the server name(abcdef), removing http prefix, I allocate that much and try to write 6+1 wide chars from source string server.

But I end up writing 9 wide chars( swprintf returns len=9), i.e. serverName becomes = abcdef:80 not abcdef.

msdn document for swprintf states that the second parameter count is max. no. of wide chars to be written. so why does it write till the end of source string?

Am I missing anything? Let me know. Thanks

void main()
{

    UINT8 server [] = "http://abcdef:80";

    CHAR* port = NULL;
    SHORT portnum = 0;
    WCHAR* serverName = NULL;

    SIZE_T inBufLen = 0;
    SIZE_T outBufBytes = 0;

      port = strrchr(server, ':');

      if (port != NULL)
      {
          portnum = atoi(port+1);
          printf(": at %d ", (int)(port-server));
          SIZE_T serverLen = port - server;

          if (strstr(server, "http") != NULL)
          {
              serverLen -= 7; //for eliminating characters from "http://"
              inBufLen = serverLen + sizeof(CHAR);
              outBufBytes = inBufLen * sizeof(WCHAR);
              serverName = (WCHAR*)malloc(outBufBytes);
              ZeroMemory(serverName, outBufBytes);

              int len = swprintf_s(serverName, outBufBytes, L"%S", server+7);
              printf("%d", len);
          }
          else
          {
              serverName = (WCHAR*)malloc((serverLen + sizeof(CHAR)) * sizeof(WCHAR));
              ZeroMemory(serverName, (serverLen + sizeof(CHAR)) * sizeof(WCHAR));

              swprintf_s(serverName, (serverLen + sizeof(CHAR)) * sizeof(WCHAR), L"%S", (CHAR*)server + 7);
          }

      }




}
Shankar S
  • 193
  • 2
  • 5
  • 16
  • You might be running into an issue where the target string isn't being terminated correctly. swprintf may do this if the number of chars is over the limit. https://stackoverflow.com/questions/7706936/is-snprintf-always-null-terminating – seand Apr 05 '20 at 20:31
  • 1
    for `swprintf_s` second parameter is Maximum number of **characters** to store, not bytes. so `(serverLen + sizeof(CHAR)) * sizeof(WCHAR)` is error - need `(serverLen + sizeof(CHAR))` – RbMm Apr 05 '20 at 20:39
  • 1
    also `outBufBytes / sizeof(WCHAR)` – RbMm Apr 05 '20 at 20:40
  • @RbMm, if I do swprintf_s(serverName, outBufBytes/sizeof(WCHAR), L"%S", server + 7); It throws me an error - buffer too small – Shankar S Apr 05 '20 at 21:30
  • @RbMm, also in the Return value section of https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/sprintf-sprintf-l-swprintf-swprintf-l-swprintf-l?view=vs-2019#return-value they specify that it returns wide characters in specific. But in Max count, they specify only characters, wouldn't it mean a normal character(i.e. a Byte), then?? – Shankar S Apr 05 '20 at 21:34
  • @seand, swprintf should terminate my dest string with null character. Also, I am allocating bytes to dest string only less than the source string. Why would it be above limit? – Shankar S Apr 05 '20 at 21:35

1 Answers1

1

The swprintf_s function does not have the truncation ability. The sizeOfBuffer is only for checking the size of the buffer.

Instead, using _snwprintf_s and specify the count parameter. Or

specify _TRUNCATE as , then _snwprintf_s writes as much of the string as will fit in buffer while leaving room for a terminating null. If the entire string (with terminating null) fits in buffer, then _snprintf_s returns the number of characters written (not including the terminating null); otherwise, _snwprintf_s returns -1 to indicate that truncation occurred.

        if (strstr(server, "http") != NULL)
        {
            serverLen -= 7; //for eliminating characters from "http://"
            inBufLen = serverLen + sizeof(CHAR);
            outBufBytes = inBufLen * sizeof(WCHAR);
            serverName = (WCHAR*)malloc(outBufBytes);
            ZeroMemory(serverName, outBufBytes);

            int len = _snwprintf_s(serverName, outBufBytes/ sizeof(WCHAR), _TRUNCATE, L"%S", server + 7);
            if (len == -1)
                len = outBufBytes / sizeof(WCHAR) - 1; //exclude terminating null
            printf("%d", len);
        }
Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • Thanks. I was also able to use mbstowcs() which allows me specify max count – Shankar S Apr 07 '20 at 05:55
  • I actually found today on the msdn document that it does say "sprintf_s guarantees that the buffer will be null-terminated unless the buffer size is zero." and "swprintf_s is a wide-character version of sprintf_s;". So the only difference between them is being wide char. So, it should support truncation ability, right? Is the document wrong or am I missing anything? @Drake – Shankar S Apr 09 '20 at 20:43
  • 1
    @ShankarS Before this sentence, *If the buffer is too small for the formatted text, including the terminating null, then the buffer is set to an empty string by placing a null character at buffer[0], and the invalid parameter handler is invoked.* So, it is also null-terminated even if buffer is too small. But the buffer is an empty string. – Drake Wu Apr 10 '20 at 01:24