We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
WarpedVRT does not permit boundless reads (sample.py)
## Expected behavior and actual behavior.

```
    def test_rasterio_vrt(self):

        import rasterio

    

        # tmp_file default crs is UTM: CRS({'init': 'epsg:32618'}

        with create_tmp_geotiff() as (tmp_file, expected):

            with rasterio.open(tmp_file) as src:

                with rasterio.vrt.WarpedVRT(src, crs="epsg:4326") as vrt:

                    expected_shape = (vrt.width, vrt.height)

                    expected_crs = vrt.crs

                    expected_res = vrt.res

                    # Value of single pixel in center of image

                    lon, lat = vrt.xy(vrt.width // 2, vrt.height // 2)

>                   expected_val = next(vrt.sample([(lon, lat)]))

test/integration/test_integration__io.py:799: 

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

../../../miniconda/envs/test/lib/python3.7/site-packages/rasterio/sample.py:43: in sample_gen

    data = read(indexes, window=window, masked=masked, boundless=True)

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???

E   ValueError: WarpedVRT does not permit boundless reads
```

## Operating system

For example: Mac OS, Windows, Linux

## Rasterio version and provenance

1.1.1 from conda-forge

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rasterio/sample.py`
Content:
```
1 # Workaround for issue #378. A pure Python generator.
2 
3 import numpy
4 
5 from rasterio.windows import Window
6 
7 
8 def sample_gen(dataset, xy, indexes=None, masked=False):
9     """Sample pixels from a dataset
10 
11     Parameters
12     ----------
13     dataset : rasterio Dataset
14         Opened in "r" mode.
15     xy : iterable
16         Pairs of x, y coordinates in the dataset's reference system.
17     indexes : int or list of int
18         Indexes of dataset bands to sample.
19     masked : bool, default: False
20         Whether to mask samples that fall outside the extent of the
21         dataset.
22 
23     Yields
24     ------
25     array
26         A array of length equal to the number of specified indexes
27         containing the dataset values for the bands corresponding to
28         those indexes.
29 
30     """
31     index = dataset.index
32     read = dataset.read
33 
34     if isinstance(indexes, int):
35         indexes = [indexes]
36 
37     for x, y in xy:
38         row_off, col_off = index(x, y)
39 #        if row_off < 0 or col_off < 0:
40 #            yield numpy.ones((dataset.count,), dtype=dataset.dtypes[0]) * dataset.nodata
41 #        else:
42         window = Window(col_off, row_off, 1, 1)
43         data = read(indexes, window=window, masked=masked, boundless=True)
44         yield data[:, 0, 0]
45
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/rasterio/sample.py b/rasterio/sample.py
--- a/rasterio/sample.py
+++ b/rasterio/sample.py
@@ -2,6 +2,7 @@
 
 import numpy
 
+from rasterio.enums import MaskFlags
 from rasterio.windows import Window
 
 
@@ -31,14 +32,24 @@
     index = dataset.index
     read = dataset.read
 
-    if isinstance(indexes, int):
+    if indexes is None:
+        indexes = dataset.indexes
+    elif isinstance(indexes, int):
         indexes = [indexes]
 
     for x, y in xy:
+
         row_off, col_off = index(x, y)
-#        if row_off < 0 or col_off < 0:
-#            yield numpy.ones((dataset.count,), dtype=dataset.dtypes[0]) * dataset.nodata
-#        else:
-        window = Window(col_off, row_off, 1, 1)
-        data = read(indexes, window=window, masked=masked, boundless=True)
-        yield data[:, 0, 0]
+
+        if row_off < 0 or col_off < 0 or row_off >= dataset.height or col_off >= dataset.width:
+            data = numpy.ones((len(indexes),), dtype=dataset.dtypes[0]) * (dataset.nodata or 0)
+            if masked:
+                mask = [False if MaskFlags.all_valid in dataset.mask_flag_enums[i - 1] else True for i in indexes]
+                yield numpy.ma.array(data, mask=mask)
+            else:
+                yield data
+
+        else:
+            window = Window(col_off, row_off, 1, 1)
+            data = read(indexes, window=window, masked=masked)
+            yield data[:, 0, 0]

{"golden_diff": "diff --git a/rasterio/sample.py b/rasterio/sample.py\n--- a/rasterio/sample.py\n+++ b/rasterio/sample.py\n@@ -2,6 +2,7 @@\n \n import numpy\n \n+from rasterio.enums import MaskFlags\n from rasterio.windows import Window\n \n \n@@ -31,14 +32,24 @@\n     index = dataset.index\n     read = dataset.read\n \n-    if isinstance(indexes, int):\n+    if indexes is None:\n+        indexes = dataset.indexes\n+    elif isinstance(indexes, int):\n         indexes = [indexes]\n \n     for x, y in xy:\n+\n         row_off, col_off = index(x, y)\n-#        if row_off < 0 or col_off < 0:\n-#            yield numpy.ones((dataset.count,), dtype=dataset.dtypes[0]) * dataset.nodata\n-#        else:\n-        window = Window(col_off, row_off, 1, 1)\n-        data = read(indexes, window=window, masked=masked, boundless=True)\n-        yield data[:, 0, 0]\n+\n+        if row_off < 0 or col_off < 0 or row_off >= dataset.height or col_off >= dataset.width:\n+            data = numpy.ones((len(indexes),), dtype=dataset.dtypes[0]) * (dataset.nodata or 0)\n+            if masked:\n+                mask = [False if MaskFlags.all_valid in dataset.mask_flag_enums[i - 1] else True for i in indexes]\n+                yield numpy.ma.array(data, mask=mask)\n+            else:\n+                yield data\n+\n+        else:\n+            window = Window(col_off, row_off, 1, 1)\n+            data = read(indexes, window=window, masked=masked)\n+            yield data[:, 0, 0]\n", "issue": "WarpedVRT does not permit boundless reads (sample.py)\n## Expected behavior and actual behavior.\r\n\r\n```\r\n    def test_rasterio_vrt(self):\r\n\r\n        import rasterio\r\n\r\n    \r\n\r\n        # tmp_file default crs is UTM: CRS({'init': 'epsg:32618'}\r\n\r\n        with create_tmp_geotiff() as (tmp_file, expected):\r\n\r\n            with rasterio.open(tmp_file) as src:\r\n\r\n                with rasterio.vrt.WarpedVRT(src, crs=\"epsg:4326\") as vrt:\r\n\r\n                    expected_shape = (vrt.width, vrt.height)\r\n\r\n                    expected_crs = vrt.crs\r\n\r\n                    expected_res = vrt.res\r\n\r\n                    # Value of single pixel in center of image\r\n\r\n                    lon, lat = vrt.xy(vrt.width // 2, vrt.height // 2)\r\n\r\n>                   expected_val = next(vrt.sample([(lon, lat)]))\r\n\r\ntest/integration/test_integration__io.py:799: \r\n\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\n../../../miniconda/envs/test/lib/python3.7/site-packages/rasterio/sample.py:43: in sample_gen\r\n\r\n    data = read(indexes, window=window, masked=masked, boundless=True)\r\n\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\n>   ???\r\n\r\nE   ValueError: WarpedVRT does not permit boundless reads\r\n```\r\n\r\n## Operating system\r\n\r\nFor example: Mac OS, Windows, Linux\r\n\r\n## Rasterio version and provenance\r\n\r\n1.1.1 from conda-forge\n", "before_files": [{"content": "# Workaround for issue #378. A pure Python generator.\n\nimport numpy\n\nfrom rasterio.windows import Window\n\n\ndef sample_gen(dataset, xy, indexes=None, masked=False):\n    \"\"\"Sample pixels from a dataset\n\n    Parameters\n    ----------\n    dataset : rasterio Dataset\n        Opened in \"r\" mode.\n    xy : iterable\n        Pairs of x, y coordinates in the dataset's reference system.\n    indexes : int or list of int\n        Indexes of dataset bands to sample.\n    masked : bool, default: False\n        Whether to mask samples that fall outside the extent of the\n        dataset.\n\n    Yields\n    ------\n    array\n        A array of length equal to the number of specified indexes\n        containing the dataset values for the bands corresponding to\n        those indexes.\n\n    \"\"\"\n    index = dataset.index\n    read = dataset.read\n\n    if isinstance(indexes, int):\n        indexes = [indexes]\n\n    for x, y in xy:\n        row_off, col_off = index(x, y)\n#        if row_off < 0 or col_off < 0:\n#            yield numpy.ones((dataset.count,), dtype=dataset.dtypes[0]) * dataset.nodata\n#        else:\n        window = Window(col_off, row_off, 1, 1)\n        data = read(indexes, window=window, masked=masked, boundless=True)\n        yield data[:, 0, 0]\n", "path": "rasterio/sample.py"}], "after_files": [{"content": "# Workaround for issue #378. A pure Python generator.\n\nimport numpy\n\nfrom rasterio.enums import MaskFlags\nfrom rasterio.windows import Window\n\n\ndef sample_gen(dataset, xy, indexes=None, masked=False):\n    \"\"\"Sample pixels from a dataset\n\n    Parameters\n    ----------\n    dataset : rasterio Dataset\n        Opened in \"r\" mode.\n    xy : iterable\n        Pairs of x, y coordinates in the dataset's reference system.\n    indexes : int or list of int\n        Indexes of dataset bands to sample.\n    masked : bool, default: False\n        Whether to mask samples that fall outside the extent of the\n        dataset.\n\n    Yields\n    ------\n    array\n        A array of length equal to the number of specified indexes\n        containing the dataset values for the bands corresponding to\n        those indexes.\n\n    \"\"\"\n    index = dataset.index\n    read = dataset.read\n\n    if indexes is None:\n        indexes = dataset.indexes\n    elif isinstance(indexes, int):\n        indexes = [indexes]\n\n    for x, y in xy:\n\n        row_off, col_off = index(x, y)\n\n        if row_off < 0 or col_off < 0 or row_off >= dataset.height or col_off >= dataset.width:\n            data = numpy.ones((len(indexes),), dtype=dataset.dtypes[0]) * (dataset.nodata or 0)\n            if masked:\n                mask = [False if MaskFlags.all_valid in dataset.mask_flag_enums[i - 1] else True for i in indexes]\n                yield numpy.ma.array(data, mask=mask)\n            else:\n                yield data\n\n        else:\n            window = Window(col_off, row_off, 1, 1)\n            data = read(indexes, window=window, masked=masked)\n            yield data[:, 0, 0]\n", "path": "rasterio/sample.py"}]}