Hi,
forget to mention that a function like this was earlier considered as  
being tricky and living dangerously.
Also we found a bug (missing break) between line 80 and 81 which will  
lead to a memory leak every time a text value is stored ...

      switch (pval->t) {
        case SQLITE_INTEGER:
          pval->n=0;
          pval->i=sqlite3_value_int64(arg);
          break;
        case SQLITE_TEXT:
          pval->n=sqlite3_value_bytes(arg);
          if (!pval->n) {
            pval->z="";
          } else {
            pval->z=sqlite3_malloc(pval->n);
            assert (pval->z); /* TODO: SQLITE_NOMEM*/
            memcpy(pval->z,sqlite3_value_text(arg),pval->n);
          }
          break;          /* <<<<<<<<<< MISSING break <<<<<<<<<< */
        case SQLITE_BLOB: /* sqlite3_value_blob instead of _text */
          pval->n=sqlite3_value_bytes(arg);
          if (!pval->n) {
            pval->z="";
          } else {
            pval->z=sqlite3_malloc(pval->n);
            assert (pval->z); /* TODO: SQLITE_NOMEM*/
            memcpy(pval->z,sqlite3_value_blob(arg),pval->n);
          }
          break;
        case SQLITE_FLOAT:
          pval->n=0;
          pval->r=sqlite3_value_double(arg);
          break;
      }
    }

I reproduced the memory leak and added a test in the sql script.
An alternative fix, instead of adding the missing break, is:

        case SQLITE_TEXT:
        case SQLITE_BLOB:
          pval->n=sqlite3_value_bytes(arg);
          if (!pval->n) {
            pval->z="";
          } else {
            pval->z=sqlite3_malloc(pval->n);
            assert (pval->z); /* TODO: SQLITE_NOMEM*/
            memcpy(pval->z,sqlite3_value_blob(arg),pval->n);
          }
          break;

Thus sqlite3_value_blob is used to get both text or blob value (like  
in sqlite3.c at line ~93615 in routine  attachFunc).

If no response I opt for the alternative fix and place it at
http://h1972688.stratoserver.net/sqlite_mprint/160223

E. Pasma

Reply via email to