Increase max key size to 1024

This commit is contained in:
Martin Raiber 2025-05-11 20:39:32 +02:00
parent 364b7e833c
commit 209fa5960b
4 changed files with 98 additions and 52 deletions

74
external/lmdb/mdb.c vendored
View File

@ -565,7 +565,7 @@ static txnid_t mdb_debug_start;
* #MDB_DUPSORT data items must fit on a node in a regular page.
*/
#ifndef MDB_MAXKEYSIZE
#define MDB_MAXKEYSIZE ((MDB_DEVEL) ? 0 : 511)
#define MDB_MAXKEYSIZE 0
#endif
/** The maximum size of a key we can write to the environment. */
@ -10444,51 +10444,51 @@ int mdb_cursor_next_leaf_page(MDB_cursor* cursor, size_t* pgno)
*pgno = cursor->mc_pg[cursor->mc_top]->mp_pgno;
return MDB_SUCCESS;
}
int mdb_cursor_get_pageno(MDB_cursor* cursor, size_t* pgno)
{
}
int mdb_cursor_get_pageno(MDB_cursor* cursor, size_t* pgno)
{
if (pgno == NULL)
return MDB_INVALID;
return MDB_INVALID;
*pgno = cursor->mc_pg[cursor->mc_top]->mp_pgno;
return MDB_SUCCESS;
}
int mdb_page_get_nkeys(MDB_cursor* mc, size_t pgno, unsigned int* nkeys)
{
if (nkeys == NULL)
return MDB_INVALID;
MDB_page* pg;
int rc = mdb_page_get(mc, pgno, &pg, NULL);
if (rc != MDB_SUCCESS)
return rc;
if (!IS_LEAF(pg))
return MDB_CORRUPTED;
if (IS_LEAF2(pg))
return MDB_CORRUPTED;
*nkeys = NUMKEYS(pg);
return MDB_SUCCESS;
return MDB_SUCCESS;
}
int mdb_page_get_nkeys(MDB_cursor* mc, size_t pgno, unsigned int* nkeys)
{
if (nkeys == NULL)
return MDB_INVALID;
MDB_page* pg;
int rc = mdb_page_get(mc, pgno, &pg, NULL);
if (rc != MDB_SUCCESS)
return rc;
if (!IS_LEAF(pg))
return MDB_CORRUPTED;
if (IS_LEAF2(pg))
return MDB_CORRUPTED;
*nkeys = NUMKEYS(pg);
return MDB_SUCCESS;
}
int mdb_page_get_val(MDB_cursor* mc, size_t pgno, unsigned int idx,
MDB_val* key, MDB_val* data)
{
MDB_page* pg;
int rc = mdb_page_get(mc, pgno, &pg, NULL);
if (rc != MDB_SUCCESS)
MDB_page* pg;
int rc = mdb_page_get(mc, pgno, &pg, NULL);
if (rc != MDB_SUCCESS)
return rc;
if (!IS_LEAF(pg))
if (!IS_LEAF(pg))
return MDB_CORRUPTED;
if (IS_LEAF2(pg))
if (IS_LEAF2(pg))
return MDB_CORRUPTED;
unsigned int nkeys = NUMKEYS(pg);
@ -10509,9 +10509,9 @@ int mdb_page_get_val(MDB_cursor* mc, size_t pgno, unsigned int idx,
int mdb_page_is_dirty(MDB_cursor* mc, size_t pgno, int* dirty)
{
MDB_page* pg;
int rc = mdb_page_get(mc, pgno, &pg, NULL);
if (rc != MDB_SUCCESS)
MDB_page* pg;
int rc = mdb_page_get(mc, pgno, &pg, NULL);
if (rc != MDB_SUCCESS)
return rc;
*dirty = ((char*)pg < mc->mc_txn->mt_env->me_map ||

View File

@ -39,6 +39,9 @@
using namespace std::chrono_literals;
// Max number of bytes in file paths. S3 max is 1024, but leave 1 + 8 + 8 bytes for versioning
const size_t c_max_path = 1024 + 1 + 8 + 8;
DEFINE_bool(symlink_lockfile_to_tmpdir, false, "Symlink LMDB lockfile to /tmp");
#ifndef _WIN32
@ -1349,7 +1352,7 @@ int SingleFileStorage::write(const std::string & fn, const char* data,
return ENODEV;
}
if (fn.size() > 255)
if (fn.size() > c_max_path)
return EINVAL;
return write_int(fn, data, data_size, data_alloc_size, last_modified, md5sum, true, no_del_old);
@ -1665,7 +1668,7 @@ SingleFileStorage::WritePrepareResult SingleFileStorage::write_prepare(const std
return WritePrepareResult{ENODEV};
}
if (fn.size() > 255)
if (fn.size() > c_max_path)
return WritePrepareResult{EINVAL};
if(data_size==0)

View File

@ -1649,6 +1649,20 @@ void S3Handler::putObject(proxygen::HTTPMessage& headers)
if(self->withBucketVersioning)
self->keyInfo.version = self->sfs.get_next_version();
if(self->keyInfo.key.size()>1024)
{
evb->runInEventBaseThread([self = self]()
{
ResponseBuilder(self->downstream_)
.status(500, "Internal error")
.body(fmt::format("Key too long"))
.sendWithEOM();
std::lock_guard lock(self->extents_mutex);
self->finished_ = true;
self->extents_cond.notify_all(); });
return;
}
const auto fpath = make_key(self->keyInfo);
auto res = self->sfs.write_prepare(fpath, self->put_remaining);
@ -2920,7 +2934,7 @@ void S3Handler::onBodyCPU(folly::EventBase *evb, int64_t offset, std::unique_ptr
{
evb->runInEventBaseThread([self = this]()
{
if(!self)
if(!self || self->finished_)
return;
ResponseBuilder(self->downstream_)
.status(500, "Internal error")
@ -2940,7 +2954,7 @@ void S3Handler::onBodyCPU(folly::EventBase *evb, int64_t offset, std::unique_ptr
{
evb->runInEventBaseThread([self = this]()
{
if(!self)
if(!self || self->finished_)
return;
ResponseBuilder(self->downstream_)
.status(400, "Bad request")
@ -2965,7 +2979,7 @@ void S3Handler::onBodyCPU(folly::EventBase *evb, int64_t offset, std::unique_ptr
{
evb->runInEventBaseThread([self = this]()
{
if(!self)
if(!self || self->finished_)
return;
ResponseBuilder(self->downstream_)
.status(500, "Internal error")
@ -2983,7 +2997,7 @@ void S3Handler::onBodyCPU(folly::EventBase *evb, int64_t offset, std::unique_ptr
{
evb->runInEventBaseThread([self = this]()
{
if(!self)
if(!self || self->finished_)
return;
ResponseBuilder(self->downstream_)
.status(500, "Internal error")
@ -3072,14 +3086,12 @@ void S3Handler::onBodyCPU(folly::EventBase *evb, int64_t offset, std::unique_ptr
{
evb->runInEventBaseThread([self = this->self]()
{
if(!self)
return;
if(!self->finished_)
ResponseBuilder(self->downstream_)
.status(500, "Internal error")
.body("Write ext error")
.sendWithEOM();
if(!self || self->finished_)
return;
ResponseBuilder(self->downstream_)
.status(500, "Internal error")
.body("Write ext error")
.sendWithEOM();
self->finished_ = true; });
return;
}

View File

@ -435,4 +435,35 @@ def test_create_bucket(hs5: Hs5Runner, tmp_path: Path):
s3_client.delete_object(Bucket=bucketname, Key="upload.txt")
s3_client.delete_bucket(Bucket=bucketname)
s3_client.delete_bucket(Bucket=bucketname)
def test_upload_long_key(hs5: Hs5Runner, tmp_path: Path):
s3_client = hs5.get_s3_client()
key = "a" * 1024
with open(tmp_path / "upload.txt", "w") as upload_file:
upload_file.write("abc")
s3_client.upload_file(upload_file.name, hs5.testbucketname(), key)
with pytest.raises(ClientError):
with io.FileIO(tmp_path / "upload.txt", "rb") as upload_file:
s3_client.put_object(Bucket=hs5.testbucketname(), Key= "a" * 1025, Body=upload_file)
dl_path = tmp_path / "download.txt"
s3_client.download_file(hs5.testbucketname(), key, str(dl_path))
assert os.stat(dl_path).st_size == 3
list = s3_client.list_objects(Bucket=hs5.testbucketname())
assert not list["IsTruncated"]
assert "Contents" in list
objs = list["Contents"]
assert len(objs) == 1
assert "Key" in objs[0] and objs[0]["Key"] == key
s3_client.delete_object(Bucket=hs5.testbucketname(), Key=key)
list = s3_client.list_objects(Bucket=hs5.testbucketname())
assert not list["IsTruncated"]
assert "Contents" not in list