title: Bounds check string pointer for return value in C function
body: <p>This is one of those, "I know there is a better way", questions.</p>
  
  <p>The below code is from a larger project I am working on, and the helper function to convert a hex value to a binary string is buried deep in the code.</p>
  
  <p>Essentially, I want to make sure that the <code>char array</code> pointed to by <code>*return_string</code> has sufficient space for the binary string generated by the function.</p>
  
  <p>As it stands, if I don't allocate enough memory, I get a SIGABRT. It would be far more elegant if I just returned -1.</p>
  
  <p>The research I have done tells me that what I am trying to do is a bit tricky, since there is really no way to bounds check an empty array via its pointer. </p>
  
  <p>For reasons that I don't understand, if I use the common macro:</p>
  
  <p><code>#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))</code></p>
  
  <p>On <code>*return_string</code>, I always get the same value. I am new to C - I am sure I am missing something elementary here.</p>
  
  <p>Anyway, here's the code. What do you all recommend? Thank you!</p>
  
  <p>(FYI - I know that as written, I do not have enough memory allocated)</p>
  
  <p>(FYI - I also know that this is not the fastest implementation of a hex to binary conversion. O(n) is good enough for this particular application)</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  
  int hex_string_to_bin_string(char *return_string, size_t bin_length, const char *input);
  
  int main(int argc, const char * argv[]) {
  
      char return_string1[12];
      char return_string2[12];
      char return_string3[12];
  
      char input1[8] = "0x4708";
      char input2[8] = "4708";
      char bad_input[8] = "47Q8";
  
      fprintf(stderr, "answer should be:\t\t\t 0100011100001000\n");
  
      //test string 1
      if(hex_string_to_bin_string(return_string1, 16, input1) &lt; 0 ) {
  
          fprintf(stderr, "FAILED return string 1\n");
  
      } else {
  
          fprintf(stderr, "return string 1:\t\t\t %s\n", return_string1);
      }
  
      //test string 2
      if(hex_string_to_bin_string(return_string2, 16, input2) &lt; 0 ) {
  
          fprintf(stderr, "FAILED return string 2\n");
  
      } else {
  
          fprintf(stderr, "return string 2:\t\t\t %s\n", return_string2);
      }
  
      //test bad input
      if(hex_string_to_bin_string(return_string3, 16, bad_input) &lt; 0) {
          fprintf(stderr, "PASSED bad character test\n");
      }
  
      else {
  
          fprintf(stderr, "FAILED bad character test\n");
      }
  
      return 0;
  }
  
  int hex_string_to_bin_string(char *return_string, size_t bin_length, const char *input) {
  
      /*
       0 - 0000
       1 - 0001
       2 - 0010
       3 - 0011
       4 - 0100
       5 - 0101
       6 - 0110
       7 - 0111
       8 - 1000
       9 - 1001
       A - 1010
       B - 1011
       C - 1100
       D - 1101
       E - 1110
       F - 1111
      */
  
      //check input to make sure length is good
      if(strlen(input) == 0 ) {
  
          return -1;
      }
  
      //check for leading '0x' and strip if necessary
      if(input[0] == '0' &amp;&amp; input[1] == 'x') {
          input += 2;
      }
  
      //loop through input and replace
      int i;
  
      char bits[5];
  
      for(i=0; i&lt;strlen(input); i++) {
  
          switch(input[i]) {
  
              case '0': {
  
                  if( snprintf(bits, sizeof(bits), "0000") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '1': {
  
                  if( snprintf(bits, sizeof(bits), "0001") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '2': {
  
                  if( snprintf(bits, sizeof(bits), "0010") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '3': {
  
                  if( snprintf(bits, sizeof(bits), "0011") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '4': {
  
                  if( snprintf(bits, sizeof(bits), "0100") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '5': {
  
                  if( snprintf(bits, sizeof(bits), "0101") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '6': {
  
                  if( snprintf(bits, sizeof(bits), "0110") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '7': {
  
                  if( snprintf(bits, sizeof(bits), "0111") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '8': {
  
                  if( snprintf(bits, sizeof(bits), "1000") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case '9': {
  
                  if( snprintf(bits, sizeof(bits), "1001") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case 'A': {
  
                  if( snprintf(bits, sizeof(bits), "1010") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case 'B': {
  
                  if( snprintf(bits, sizeof(bits), "1011") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case 'C': {
  
                  if( snprintf(bits, sizeof(bits), "1100") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case 'D': {
  
                  if( snprintf(bits, sizeof(bits), "1101") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case 'E': {
  
                  if( snprintf(bits, sizeof(bits), "1110") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
              case 'F': {
  
                  if( snprintf(bits, sizeof(bits), "1111") &lt; 0) {
  
                      return -1;
                  }
  
                  break;
              }
  
              default: {
  
                  return -1;
              }
          }
  
          if(i == 0) {
              snprintf(return_string, bin_length+1, "%s", bits);
          }
  
          else {
              snprintf(return_string, bin_length+1, "%s%s", return_string, bits);
          }
      }
  
      return 0;
  }
  </code></pre>