diff --git a/src/libpmemobj/heap.c b/src/libpmemobj/heap.c
index 8b948484f29aa473122f6c8002719559652906b9..a3e4a83b7087a198863ccc8a97b54137c27b9d37 100644
--- a/src/libpmemobj/heap.c
+++ b/src/libpmemobj/heap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2019, Intel Corporation
+ * Copyright 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -359,9 +359,11 @@ zone_calc_size_idx(uint32_t zone_id, unsigned max_zone, size_t heap_size)
 	size_t zone_raw_size = heap_size - zone_id * ZONE_MAX_SIZE;
 
 	ASSERT(zone_raw_size >= (sizeof(struct zone_header) +
-			sizeof(struct chunk_header) * MAX_CHUNK));
+			sizeof(struct chunk_header) * MAX_CHUNK) +
+			sizeof(struct heap_header));
 	zone_raw_size -= sizeof(struct zone_header) +
-		sizeof(struct chunk_header) * MAX_CHUNK;
+		sizeof(struct chunk_header) * MAX_CHUNK +
+		sizeof(struct heap_header);
 
 	size_t zone_size_idx = zone_raw_size / CHUNKSIZE;
 	ASSERT(zone_size_idx <= UINT32_MAX);
@@ -380,8 +382,7 @@ heap_zone_init(struct palloc_heap *heap, uint32_t zone_id,
 	uint32_t size_idx = zone_calc_size_idx(zone_id, heap->rt->nzones,
 			*heap->sizep);
 
-	ASSERT(size_idx - first_chunk_id > 0);
-
+	ASSERT(size_idx > first_chunk_id);
 	memblock_huge_init(heap, first_chunk_id, zone_id,
 		size_idx - first_chunk_id);
 
@@ -1325,6 +1326,7 @@ heap_zone_update_if_needed(struct palloc_heap *heap)
 
 		size_t size_idx = zone_calc_size_idx(i, heap->rt->nzones,
 			*heap->sizep);
+
 		if (size_idx == z->header.size_idx)
 			continue;
 
diff --git a/src/test/obj_heap/obj_heap.c b/src/test/obj_heap/obj_heap.c
index e241fff5ecc43dfd4d75081f8bab7a29740c6533..7fb7247aa32df0eac96a56dd2b154b27690529d0 100644
--- a/src/test/obj_heap/obj_heap.c
+++ b/src/test/obj_heap/obj_heap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2019, Intel Corporation
+ * Copyright 2015-2020, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -301,6 +301,77 @@ test_heap(void)
 	MUNMAP_ANON_ALIGNED(mpop, MOCK_POOL_SIZE);
 }
 
+/*
+ * test_heap_with_size -- tests scenarios with not-nicely aligned sizes
+ */
+static void
+test_heap_with_size()
+{
+	/*
+	 * To trigger bug with incorrect metadata alignment we need to
+	 * use a size that uses exactly the size used in bugged zone size
+	 * calculations.
+	 */
+	size_t size = PMEMOBJ_MIN_POOL + sizeof(struct zone_header) +
+		sizeof(struct chunk_header) * MAX_CHUNK +
+		sizeof(PMEMobjpool);
+
+	struct mock_pop *mpop = MMAP_ANON_ALIGNED(size,
+		Ut_mmap_align);
+	PMEMobjpool *pop = &mpop->p;
+	memset(pop, 0, size);
+	pop->heap_offset = (uint64_t)((uint64_t)&mpop->heap - (uint64_t)mpop);
+	pop->p_ops.persist = obj_heap_persist;
+	pop->p_ops.flush = obj_heap_flush;
+	pop->p_ops.drain = obj_heap_drain;
+	pop->p_ops.memset = obj_heap_memset;
+	pop->p_ops.base = pop;
+	pop->set = MALLOC(sizeof(*(pop->set)));
+	pop->set->options = 0;
+	pop->set->directory_based = 0;
+
+	void *heap_start = (char *)pop + pop->heap_offset;
+	uint64_t heap_size = size - sizeof(PMEMobjpool);
+	struct palloc_heap *heap = &pop->heap;
+	struct pmem_ops *p_ops = &pop->p_ops;
+
+	UT_ASSERT(heap_check(heap_start, heap_size) != 0);
+	UT_ASSERT(heap_init(heap_start, heap_size,
+		&pop->heap_size, p_ops) == 0);
+	UT_ASSERT(heap_boot(heap, heap_start, heap_size,
+		&pop->heap_size,
+		pop, p_ops, NULL, pop->set) == 0);
+	UT_ASSERT(heap_buckets_init(heap) == 0);
+	UT_ASSERT(pop->heap.rt != NULL);
+
+	struct bucket *b_def = heap_bucket_acquire(heap,
+		DEFAULT_ALLOC_CLASS_ID, HEAP_ARENA_PER_THREAD);
+
+	struct memory_block mb;
+	mb.size_idx = 1;
+	while (heap_get_bestfit_block(heap, b_def, &mb) == 0)
+		;
+
+	/* mb should now be the last chunk in the heap */
+	char *ptr = mb.m_ops->get_real_data(&mb);
+	size_t s = mb.m_ops->get_real_size(&mb);
+
+	/* last chunk should be within the heap and accessible */
+	UT_ASSERT((size_t)ptr + s <= (size_t)mpop + size);
+
+	VALGRIND_DO_MAKE_MEM_DEFINED(ptr, s);
+	memset(ptr, 0xc, s);
+
+	heap_bucket_release(heap, b_def);
+
+	UT_ASSERT(heap_check(heap_start, heap_size) == 0);
+	heap_cleanup(heap);
+	UT_ASSERT(heap->rt == NULL);
+
+	FREE(pop->set);
+	MUNMAP_ANON_ALIGNED(mpop, size);
+}
+
 static void
 test_recycler(void)
 {
@@ -458,6 +529,7 @@ main(int argc, char *argv[])
 	START(argc, argv, "obj_heap");
 
 	test_heap();
+	test_heap_with_size();
 	test_recycler();
 
 	DONE(NULL);