X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Frepo_solv.c;h=8dfcc7607caf57f1ab4550e3fe8689135a723b79;hb=709d8403945de1ac569f14a89b953b900c2bded3;hp=2723465926abf742348d7ad567d341e027c9f7c8;hpb=3bf73c639f7e8c5825024a889597b8abc1eb64fa;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/repo_solv.c b/src/repo_solv.c index 2723465..8dfcc76 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -465,8 +465,9 @@ key_cmp (const void *pa, const void *pb) static void repodata_load_solv(Repodata *data); static void -parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo) +parse_external_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel) { + Repo *repo = maindata->repo; Id key, id; Id *ida, *ide; Repodata *data; @@ -476,6 +477,7 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned data = repo->repodata + repo->nrepodata++; memset(data, 0, sizeof(*data)); data->repo = repo; + data->pagefd = -1; data->state = REPODATA_STUB; data->loadcallback = repodata_load_solv; @@ -492,12 +494,12 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned } /* read_idarray writes a terminating 0, that's why the + 1 */ ida = sat_calloc(keys[key].size + 1, sizeof(Id)); - ide = read_idarray(maindata, 0, 0, ida, ida + keys[key].size + 1); + ide = read_idarray(maindata, numid, idmap, ida, ida + keys[key].size + 1); n = ide - ida - 1; if (n & 1) { pool_debug (mypool, SAT_ERROR, "invalid attribute data\n"); - data->error = SOLV_ERROR_CORRUPT; + maindata->error = SOLV_ERROR_CORRUPT; return; } data->nkeys = 1 + (n >> 1); @@ -505,14 +507,8 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned memset(data->keys, 0, sizeof(Repokey)); for (i = 1, ide = ida; i < data->nkeys; i++) { - if (*ide >= numid) - { - pool_debug (mypool, SAT_ERROR, "invalid attribute data\n"); - data->error = SOLV_ERROR_CORRUPT; - return; - } - data->keys[i].name = idmap ? idmap[*ide++] : *ide++; - data->keys[i].type = idmap ? idmap[*ide++] : *ide++; + data->keys[i].name = *ide++; + data->keys[i].type = *ide++; data->keys[i].size = 0; data->keys[i].storage = 0; } @@ -526,7 +522,7 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned else { char buf[1024]; - unsigned len = sizeof (buf); + unsigned len = sizeof(buf); char *filename = buf; read_str(maindata, &filename, &len); data->location = strdup(filename); @@ -541,6 +537,37 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned } } +static void +parse_info_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel) +{ + Id key, id; + Id *ida; + while ((key = *keyp++) != 0) + { + id = keys[key].name; + if (id == REPODATA_ADDEDFILEPROVIDES && keys[key].type == REPOKEY_TYPE_REL_IDARRAY) + { + Id old = 0; + /* + 1 just in case */ + ida = sat_calloc(keys[key].size + 1, sizeof(Id)); + read_idarray(maindata, 0, 0, ida, ida + keys[key].size + 1); + maindata->addedfileprovides = ida; + for (; *ida; ida++) + { + old += *ida - 1; + if (old >= numid) + { + *ida = 0; + break; + } + *ida = idmap ? idmap[old] : old; + } + continue; + } + skip_item(maindata, keys[key].type, numid, numrel); + } +} + /*-----------------------------------------------------------------*/ @@ -596,6 +623,32 @@ incore_add_blob(Repodata *data, unsigned char *buf, int len) } static void +incore_map_idarray(Repodata *data, unsigned char *dp, Id *map, Id max) +{ + /* We have to map the IDs, which might also change + the necessary number of bytes, so we can't just copy + over the blob and adjust it. */ + for (;;) + { + Id id; + int eof; + dp = data_read_ideof(dp, &id, &eof); + if (max && id >= max) + { + pool_debug(mypool, SAT_ERROR, "incore_map_idarray: id too large (%u/%u)\n", id, max); + data->error = SOLV_ERROR_ID_RANGE; + break; + } + id = map[id]; + if (id >= 64) + id = (id & 63) | ((id & ~63) << 1); + incore_add_id(data, eof ? id : id | 64); + if (eof) + break; + } +} + +static void incore_add_u32(Repodata *data, unsigned int x) { unsigned char *dp; @@ -796,6 +849,8 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) char *pp = prefix; char *old_str = 0; char *dest = strsp; + int freesp = sizeid; + if (pfsize && fread(prefix, pfsize, 1, fp) != 1) { pool_debug(pool, SAT_ERROR, "read error while reading strings\n"); @@ -805,7 +860,14 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) for (i = 1; i < numid; i++) { int same = (unsigned char)*pp++; - size_t len = strlen (pp) + 1; + size_t len = strlen(pp) + 1; + freesp -= same + len; + if (freesp < 0) + { + pool_debug(pool, SAT_ERROR, "overflow while expanding strings\n"); + sat_free(prefix); + return SOLV_ERROR_OVERFLOW; + } if (same) memcpy(dest, old_str, same); memcpy(dest + same, pp, len); @@ -814,6 +876,11 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) dest += same + len; } sat_free(prefix); + if (freesp != 0) + { + pool_debug(pool, SAT_ERROR, "expanding strings size mismatch\n"); + return SOLV_ERROR_CORRUPT; + } } strsp[sizeid] = 0; /* make string space \0 terminated */ sp = strsp; @@ -887,7 +954,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) { sat_free(hashtbl); sat_free(idmap); - pool_debug(pool, SAT_ERROR, "not enough strings\n"); + pool_debug(pool, SAT_ERROR, "not enough strings %d %d\n", i, numid); return SOLV_ERROR_OVERFLOW; } if (!*sp) /* empty string */ @@ -1112,10 +1179,16 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == REPOKEY_TYPE_VOID) { /* external data for some ids */ - parse_repodata(&data, keyp, keys, idmap, numid, numrel, repo); + parse_external_repodata(&data, keyp, keys, idmap, numid, numrel); + } + else if (keys[key].name == REPODATA_INFO) + { + parse_info_repodata(&data, keyp, keys, idmap, numid, numrel); } else - skip_schema(&data, keyp, keys, numid, numrel); + { + skip_schema(&data, keyp, keys, numid, numrel); + } } @@ -1174,7 +1247,11 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) s = 0; if (have_xdata) - repodata_extend_block(&data, data.start, numsolv); + { + /* reserve one byte so that all offsets are not zero */ + incore_add_id(&data, 0); + repodata_extend_block(&data, data.start, numsolv); + } left = 0; buf = sat_calloc(maxsize + 4, 1); @@ -1271,8 +1348,8 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key dps = dp; dp = data_skip(dp, REPOKEY_TYPE_IDARRAY); if (keys[key].storage == KEY_STORAGE_INCORE && idmap) - abort(); - if (keys[key].storage == KEY_STORAGE_INCORE) + incore_map_idarray(&data, dps, idmap, numid); + else if (keys[key].storage == KEY_STORAGE_INCORE) incore_add_blob(&data, dps, dp - dps); break; }