SQLite

Check-in [5fed67033c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a zipfile problem with adding new directories to an archive.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5fed67033c9dd4492bf8cfcf98874284581f448d8cc84fa5470dde239f218375
User & Date: dan 2018-01-09 10:29:34.950
Context
2018-01-09
14:27
Attempt to fix the fileio.c extension so that it builds on MinGW-64. (check-in: a7446d3217 user: drh tags: trunk)
10:29
Fix a zipfile problem with adding new directories to an archive. (check-in: 5fed67033c user: dan tags: trunk)
07:16
Fix a problem in zipfile.c found by -fsanitize. (check-in: 4fe697fa6c user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/misc/zipfile.c.
1148
1149
1150
1151
1152
1153
1154
1155





1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
  if( rc==SQLITE_OK ){
    rc = zipfileAppendData(pTab, pData, nData);
  }

  return rc;
}

static int zipfileGetMode(ZipfileTab *pTab, sqlite3_value *pVal, u32 *pMode){





  const char *z = (const char*)sqlite3_value_text(pVal);
  u32 mode = 0;
  if( z==0 ){
    mode = S_IFREG + 0644;                 /* -rw-r--r-- */
  }else if( z[0]>=0 && z[0]<=9 ){
    mode = (unsigned int)sqlite3_value_int(pVal);
  }else{
    const char zTemplate[11] = "-rwxrwxrwx";
    int i;
    if( strlen(z)!=10 ) goto parse_error;
    switch( z[0] ){







|
>
>
>
>
>



|







1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
  if( rc==SQLITE_OK ){
    rc = zipfileAppendData(pTab, pData, nData);
  }

  return rc;
}

static int zipfileGetMode(
  ZipfileTab *pTab, 
  sqlite3_value *pVal, 
  u32 defaultMode,                /* Value to use if pVal IS NULL */
  u32 *pMode
){
  const char *z = (const char*)sqlite3_value_text(pVal);
  u32 mode = 0;
  if( z==0 ){
    mode = defaultMode;
  }else if( z[0]>=0 && z[0]<=9 ){
    mode = (unsigned int)sqlite3_value_int(pVal);
  }else{
    const char zTemplate[11] = "-rwxrwxrwx";
    int i;
    if( strlen(z)!=10 ) goto parse_error;
    switch( z[0] ){
1203
1204
1205
1206
1207
1208
1209




1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231


1232
1233
1234
1235

1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259

1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275

1276
1277
1278





















1279
1280
1281
1282
1283
1284
1285
  const char *zPath;              /* Path for new entry */
  int nPath;                      /* strlen(zPath) */
  const u8 *pData = 0;            /* Pointer to buffer containing content */
  int nData = 0;                  /* Size of pData buffer in bytes */
  int iMethod = 0;                /* Compression method for new entry */
  u8 *pFree = 0;                  /* Free this */
  ZipfileCDS cds;                 /* New Central Directory Structure entry */





  assert( pTab->zFile );
  assert( pTab->pWriteFd );

  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
    i64 iDelete = sqlite3_value_int64(apVal[0]);
    ZipfileEntry *p;
    for(p=pTab->pFirstEntry; p; p=p->pNext){
      if( p->iRowid==iDelete ){
        p->bDeleted = 1;
        break;
      }
    }
    if( nVal==1 ) return SQLITE_OK;
  }

  zPath = (const char*)sqlite3_value_text(apVal[2]);
  nPath = (int)strlen(zPath);
  rc = zipfileGetMode(pTab, apVal[3], &mode);
  if( rc!=SQLITE_OK ) return rc;
  if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){
    mTime = (sqlite3_int64)time(0);


  }else{
    mTime = sqlite3_value_int64(apVal[4]);
  }


  if( sqlite3_value_type(apVal[5])==SQLITE_NULL    /* sz */
   && sqlite3_value_type(apVal[6])==SQLITE_NULL    /* rawdata */
   && sqlite3_value_type(apVal[7])!=SQLITE_NULL    /* data */
  ){
    const u8 *aIn = sqlite3_value_blob(apVal[7]);
    int nIn = sqlite3_value_bytes(apVal[7]);
    int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
    
    iMethod = sqlite3_value_int(apVal[8]);
    sz = nIn;
    if( iMethod!=0 && iMethod!=8 ){
      rc = SQLITE_CONSTRAINT;
    }else if( bAuto || iMethod ){
      rc = zipfileDeflate(pTab, aIn, nIn, &pFree, &nData);
      if( rc==SQLITE_OK ){
        if( iMethod || nData<nIn ){
          iMethod = 8;
          pData = pFree;
        }else{
          pData = aIn;
          nData = nIn;
        }
      }
    }

  }else 
  if( sqlite3_value_type(apVal[5])!=SQLITE_NULL    /* sz */
   && sqlite3_value_type(apVal[6])!=SQLITE_NULL    /* rawdata */
   && sqlite3_value_type(apVal[7])==SQLITE_NULL    /* data */
   && sqlite3_value_type(apVal[8])!=SQLITE_NULL    /* method */
  ){
    pData = sqlite3_value_blob(apVal[6]);
    nData = sqlite3_value_bytes(apVal[6]);
    sz = sqlite3_value_int(apVal[5]);
    iMethod = sqlite3_value_int(apVal[8]);
    if( iMethod<0 || iMethod>65535 ){
      pTab->base.zErrMsg = sqlite3_mprintf(
          "zipfile: invalid compression method: %d", iMethod
      );
      rc = SQLITE_ERROR;
    }

  }else{
    rc = SQLITE_CONSTRAINT;
  }






















  if( rc==SQLITE_OK ){
    /* Create the new CDS record. */
    memset(&cds, 0, sizeof(cds));
    cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
    cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
    cds.flags = ZIPFILE_NEWENTRY_FLAGS;







>
>
>
>
















|
<
<
|
|
|
>
>
|
<

|
>
|
<
<
<




















>
|
<
|
|
<
<










>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235


1236
1237
1238
1239
1240
1241

1242
1243
1244
1245



1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267

1268
1269


1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
  const char *zPath;              /* Path for new entry */
  int nPath;                      /* strlen(zPath) */
  const u8 *pData = 0;            /* Pointer to buffer containing content */
  int nData = 0;                  /* Size of pData buffer in bytes */
  int iMethod = 0;                /* Compression method for new entry */
  u8 *pFree = 0;                  /* Free this */
  ZipfileCDS cds;                 /* New Central Directory Structure entry */

  int bIsDir = 0;

  int mNull;

  assert( pTab->zFile );
  assert( pTab->pWriteFd );

  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
    i64 iDelete = sqlite3_value_int64(apVal[0]);
    ZipfileEntry *p;
    for(p=pTab->pFirstEntry; p; p=p->pNext){
      if( p->iRowid==iDelete ){
        p->bDeleted = 1;
        break;
      }
    }
    if( nVal==1 ) return SQLITE_OK;
  }

  mNull = (sqlite3_value_type(apVal[5])==SQLITE_NULL ? 0x0 : 0x8)  /* sz */


        + (sqlite3_value_type(apVal[6])==SQLITE_NULL ? 0x0 : 0x4)  /* rawdata */
        + (sqlite3_value_type(apVal[7])==SQLITE_NULL ? 0x0 : 0x2)  /* data */
        + (sqlite3_value_type(apVal[8])==SQLITE_NULL ? 0x0 : 0x1); /* method */
  if( mNull==0x00 ){     
    /* All four are NULL - this must be a directory */
    bIsDir = 1;

  }
  else if( mNull==0x2 || mNull==0x3 ){
    /* Value specified for "data", and possibly "method". This must be
    ** a regular file or a symlink. */



    const u8 *aIn = sqlite3_value_blob(apVal[7]);
    int nIn = sqlite3_value_bytes(apVal[7]);
    int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
    
    iMethod = sqlite3_value_int(apVal[8]);
    sz = nIn;
    if( iMethod!=0 && iMethod!=8 ){
      rc = SQLITE_CONSTRAINT;
    }else if( bAuto || iMethod ){
      rc = zipfileDeflate(pTab, aIn, nIn, &pFree, &nData);
      if( rc==SQLITE_OK ){
        if( iMethod || nData<nIn ){
          iMethod = 8;
          pData = pFree;
        }else{
          pData = aIn;
          nData = nIn;
        }
      }
    }
  }
  else if( mNull==0x0D ){

    /* Values specified for "sz", "rawdata" and "method". In other words,
    ** pre-compressed data is being inserted.  */


    pData = sqlite3_value_blob(apVal[6]);
    nData = sqlite3_value_bytes(apVal[6]);
    sz = sqlite3_value_int(apVal[5]);
    iMethod = sqlite3_value_int(apVal[8]);
    if( iMethod<0 || iMethod>65535 ){
      pTab->base.zErrMsg = sqlite3_mprintf(
          "zipfile: invalid compression method: %d", iMethod
      );
      rc = SQLITE_ERROR;
    }
  }
  else{
    rc = SQLITE_CONSTRAINT;
  }

  if( rc==SQLITE_OK ){
    rc = zipfileGetMode(pTab, apVal[3], 
        (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)), &mode
    );
    if( rc==SQLITE_OK && (bIsDir == ((mode & S_IFDIR)==0)) ){
      /* The "mode" attribute is a directory, but data has been specified.
      ** Or vice-versa - no data but "mode" is a file or symlink.  */
      rc = SQLITE_CONSTRAINT;
    }
  }

  if( rc==SQLITE_OK ){
    zPath = (const char*)sqlite3_value_text(apVal[2]);
    nPath = (int)strlen(zPath);
    if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){
      mTime = (sqlite3_int64)time(0);
    }else{
      mTime = sqlite3_value_int64(apVal[4]);
    }
  }

  if( rc==SQLITE_OK ){
    /* Create the new CDS record. */
    memset(&cds, 0, sizeof(cds));
    cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
    cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
    cds.flags = ZIPFILE_NEWENTRY_FLAGS;
Changes to test/zipfile.test.
74
75
76
77
78
79
80






















81
82
83
  SELECT name FROM zz;
} {f.txt g.txt h.txt i.txt}

do_execsql_test 1.6.0 {
  DELETE FROM zz WHERE name='g.txt';
  SELECT name FROM zz;
} {f.txt h.txt i.txt}























finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  SELECT name FROM zz;
} {f.txt g.txt h.txt i.txt}

do_execsql_test 1.6.0 {
  DELETE FROM zz WHERE name='g.txt';
  SELECT name FROM zz;
} {f.txt h.txt i.txt}

#-------------------------------------------------------------------------
db close
forcedelete test.zip
reset_db
load_static_extension db zipfile
do_execsql_test 2.1 {
  CREATE VIRTUAL TABLE zzz USING zipfile('test.zip');
  INSERT INTO zzz(name, mode) VALUES('dirname', 'drwxr-xr-x');
  SELECT name, mode, data FROM zzz;
} {dirname 16877 {}}
do_execsql_test 2.2 {
  INSERT INTO zzz(name, data) VALUES('dirname2', NULL);
  INSERT INTO zzz(name, data) VALUES('dirname2/file1.txt', 'abcdefghijklmnop');
  SELECT name, mode, data FROM zzz;
} {
  dirname 16877 {}
  dirname2 16877 {}
  dirname2/file1.txt 33188 abcdefghijklmnop
}



finish_test