Index: /trunk/src/VBox/Storage/VD.cpp
===================================================================
--- /trunk/src/VBox/Storage/VD.cpp	(revision 75348)
+++ /trunk/src/VBox/Storage/VD.cpp	(revision 75349)
@@ -595,27 +595,34 @@
 {
     uint64_t cbImage = 0;
-    PCVDREGIONLIST pRegionList = NULL;
-    int rc = pImage->Backend->pfnQueryRegions(pImage->pBackendData, &pRegionList);
-    if (RT_SUCCESS(rc))
-    {
-        if (pRegionList->fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
-        {
-            PVDREGIONLIST pRegionListConv = NULL;
-            rc = vdRegionListConv(pRegionList, 0, &pRegionListConv);
-            if (RT_SUCCESS(rc))
+
+    if (pImage->cbImage == VD_IMAGE_SIZE_UNINITIALIZED)
+    {
+        PCVDREGIONLIST pRegionList = NULL;
+        int rc = pImage->Backend->pfnQueryRegions(pImage->pBackendData, &pRegionList);
+        if (RT_SUCCESS(rc))
+        {
+            if (pRegionList->fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
             {
-                for (uint32_t i = 0; i < pRegionListConv->cRegions; i++)
-                    cbImage += pRegionListConv->aRegions[i].cRegionBlocksOrBytes;
-
-                VDRegionListFree(pRegionListConv);
+                PVDREGIONLIST pRegionListConv = NULL;
+                rc = vdRegionListConv(pRegionList, 0, &pRegionListConv);
+                if (RT_SUCCESS(rc))
+                {
+                    for (uint32_t i = 0; i < pRegionListConv->cRegions; i++)
+                        cbImage += pRegionListConv->aRegions[i].cRegionBlocksOrBytes;
+
+                    VDRegionListFree(pRegionListConv);
+                }
             }
-        }
-        else
-            for (uint32_t i = 0; i < pRegionList->cRegions; i++)
-                cbImage += pRegionList->aRegions[i].cRegionBlocksOrBytes;
-
-        AssertPtr(pImage->Backend->pfnRegionListRelease);
-        pImage->Backend->pfnRegionListRelease(pImage->pBackendData, pRegionList);
-    }
+            else
+                for (uint32_t i = 0; i < pRegionList->cRegions; i++)
+                    cbImage += pRegionList->aRegions[i].cRegionBlocksOrBytes;
+
+            AssertPtr(pImage->Backend->pfnRegionListRelease);
+            pImage->Backend->pfnRegionListRelease(pImage->pBackendData, pRegionList);
+            pImage->cbImage = cbImage; /* Cache the value. */
+        }
+    }
+    else
+        cbImage = pImage->cbImage;
 
     return cbImage;
@@ -3312,4 +3319,5 @@
 {
     RT_NOREF8(pvUser, pStorage, uOffset, paSegments, cSegments, cbRead, pvCompletion, ppTask);
+    AssertFailed();
     return VERR_NOT_IMPLEMENTED;
 }
@@ -3324,4 +3332,5 @@
 {
     RT_NOREF8(pvUser, pStorage, uOffset, paSegments, cSegments, cbWrite, pvCompletion, ppTask);
+    AssertFailed();
     return VERR_NOT_IMPLEMENTED;
 }
@@ -3334,4 +3343,5 @@
 {
     RT_NOREF4(pvUser, pStorage, pvCompletion, ppTask);
+    AssertFailed();
     return VERR_NOT_IMPLEMENTED;
 }
@@ -5627,4 +5637,5 @@
         }
 
+        pImage->cbImage     = VD_IMAGE_SIZE_UNINITIALIZED;
         pImage->VDIo.pDisk  = pDisk;
         pImage->pVDIfsImage = pVDIfsImage;
@@ -6274,4 +6285,5 @@
             break;
         }
+        pImage->cbImage     = VD_IMAGE_SIZE_UNINITIALIZED;
         pImage->VDIo.pDisk  = pDisk;
         pImage->pVDIfsImage = pVDIfsImage;
@@ -6577,4 +6589,5 @@
         }
 
+        pImage->cbImage     = VD_IMAGE_SIZE_UNINITIALIZED;
         pImage->VDIo.pDisk  = pDisk;
         pImage->pVDIfsImage = pVDIfsImage;
@@ -7064,7 +7077,17 @@
                          pCurrImage = pCurrImage->pPrev)
                     {
-                        rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
-                                                          uOffset, cbThisRead,
-                                                          &IoCtx, &cbThisRead);
+                        /*
+                         * Skip reading when offset exceeds image size which can happen when the target is
+                         * bigger than the source.
+                         */
+                        if (uOffset < pCurrImage->cbImage)
+                        {
+                            cbThisRead = RT_MIN(cbThisRead, pCurrImage->cbImage - uOffset);
+                            rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
+                                                              uOffset, cbThisRead,
+                                                              &IoCtx, &cbThisRead);
+                        }
+                        else
+                            rc = VERR_VD_BLOCK_FREE;
                     }
 
@@ -7191,7 +7214,17 @@
                      pCurrImage = pCurrImage->pPrev)
                 {
-                    rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
-                                                           uOffset, cbThisRead,
-                                                           &IoCtx, &cbThisRead);
+                    /*
+                     * Skip reading when offset exceeds image size which can happen when the target is
+                     * bigger than the source.
+                     */
+                    if (uOffset < pCurrImage->cbImage)
+                    {
+                        cbThisRead = RT_MIN(cbThisRead, pCurrImage->cbImage - uOffset);
+                        rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
+                                                          uOffset, cbThisRead,
+                                                          &IoCtx, &cbThisRead);
+                    }
+                    else
+                        rc = VERR_VD_BLOCK_FREE;
                 }
 
@@ -7980,4 +8013,7 @@
                                             pImage->pVDIfsImage,
                                             pVDIfsOperation);
+        /* Mark the image size as uninitialized so it gets recalculated the next time. */
+        if (RT_SUCCESS(rc))
+            pImage->cbImage = VD_IMAGE_SIZE_UNINITIALIZED;
     } while (0);
 
Index: /trunk/src/VBox/Storage/VDInternal.h
===================================================================
--- /trunk/src/VBox/Storage/VDInternal.h	(revision 75348)
+++ /trunk/src/VBox/Storage/VDInternal.h	(revision 75349)
@@ -74,4 +74,6 @@
     /** Link to child image descriptor, if any. */
     struct VDIMAGE     *pNext;
+    /** Cached image size. */
+    uint64_t           cbImage;
     /** Container base filename. (UTF-8) */
     char               *pszFilename;
@@ -91,4 +93,7 @@
     VDIO                VDIo;
 } VDIMAGE, *PVDIMAGE;
+
+/** The special uninitialized size value for he image. */
+#define VD_IMAGE_SIZE_UNINITIALIZED UINT64_C(0)
 
 /**
