Repository: vyperlang/vyper

Issue:
Usage of kwargs not prevented for `range(N,M)` or `range(x,x+N)`  
### Version Information

* vyper Version (output of `vyper --version`): 0.3.10+commit.855f7349
* OS: OSX
* Python Version (output of `python --version`): 3.11.4

### What's your issue about?

Using the keyword argument `bound` for ranges on the form `range(N, M)` and `range(x, x + N)` is not syntactically forbidden. The generated bytecode of the following examples is identical to the one that would have been generated without having the `bound` keyword.

```Vyper
@external
def bar():
    for i in range(1,2,bound=2):
        pass
```
```Vyper
@external
def bar():
    x:uint256 = 1
    for i in range(x,x+1,bound=2):
        pass
```

### How can it be fixed?

Only allow ranges on the form `range(N)` to have kwargs.

Discussion:
codecov-commenter: ## [Codecov](https://app.codecov.io/gh/vyperlang/vyper/pull/3551?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang) Report
> Merging [#3551](https://app.codecov.io/gh/vyperlang/vyper/pull/3551?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang) (f3246a3) into [master](https://app.codecov.io/gh/vyperlang/vyper/commit/cfda16c734ecddc170079817cd96b14e4fe24586?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang) (cfda16c) will **decrease** coverage by `2.49%`.
> Report is 2 commits behind head on master.
> The diff coverage is `100.00%`.

:exclamation: Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please [install the Github App Integration](https://github.com/apps/codecov) for your organization. [Read more](https://about.codecov.io/blog/codecov-is-updating-its-github-integration/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang).

```diff
@@            Coverage Diff             @@
##           master    #3551      +/-   ##
==========================================
- Coverage   89.11%   86.62%   -2.49%     
==========================================
  Files          85       85              
  Lines       11362    11364       +2     
  Branches     2584     2585       +1     
==========================================
- Hits        10125     9844     -281     
- Misses        816     1064     +248     
- Partials      421      456      +35     
```


| [Files Changed](https://app.codecov.io/gh/vyperlang/vyper/pull/3551?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang) | Coverage Δ | |
|---|---|---|
| [vyper/semantics/analysis/local.py](https://app.codecov.io/gh/vyperlang/vyper/pull/3551?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang#diff-dnlwZXIvc2VtYW50aWNzL2FuYWx5c2lzL2xvY2FsLnB5) | `91.66% <100.00%> (+0.04%)` | :arrow_up: |

... and [13 files with indirect coverage changes](https://app.codecov.io/gh/vyperlang/vyper/pull/3551/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang)

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vyperlang)


Patch:
diff --git a/docs/built-in-functions.rst b/docs/built-in-functions.rst
index 74e85604..bfaa8fdd 100644
--- a/docs/built-in-functions.rst
+++ b/docs/built-in-functions.rst
@@ -379,7 +379,11 @@ Cryptography
     * ``s``: second 32 bytes of signature
     * ``v``: final 1 byte of signature
 
-    Returns the associated address, or ``0`` on error.
+    Returns the associated address, or ``empty(address)`` on error.
+
+    .. note::
+
+         Prior to Vyper ``0.3.10``, the ``ecrecover`` function could return an undefined (possibly nonzero) value for invalid inputs to ``ecrecover``. For more information, please see `GHSA-f5x6-7qgp-jhf3 <https://github.com/vyperlang/vyper/security/advisories/GHSA-f5x6-7qgp-jhf3>`_.
 
     .. code-block:: python
 
@@ -573,6 +577,24 @@ Math
         >>> ExampleContract.foo(3.1337)
         4
 
+.. py:function:: epsilon(typename) -> Any
+
+    Returns the smallest non-zero value for a decimal type.
+
+    * ``typename``: Name of the decimal type (currently only ``decimal``)
+
+    .. code-block:: python
+
+        @external
+        @view
+        def foo() -> decimal:
+            return epsilon(decimal)
+
+    .. code-block:: python
+
+        >>> ExampleContract.foo()
+        Decimal('1E-10')
+
 .. py:function:: floor(value: decimal) -> int256
 
     Round a decimal down to the nearest integer.
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index 9a638469..f408c5c0 100644
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -336,6 +336,7 @@ Special thanks to @skellet0r for some major features in this release!
 
 v0.3.0
 *******
+⚠️ A critical security vulnerability has been discovered in this version and we strongly recommend using version `0.3.1 <https://github.com/vyperlang/vyper/releases/tag/v0.3.1>`_ or higher. For more information, please see the Security Advisory `GHSA-5824-cm3x-3c38 <https://github.com/vyperlang/vyper/security/advisories/GHSA-5824-cm3x-3c38>`_.
 
 Date released: 2021-10-04
 
@@ -368,6 +369,7 @@ Special thanks to contributions from @skellet0r and @benjyz for this release!
 
 v0.2.16
 *******
+⚠️ A critical security vulnerability has been discovered in this version and we strongly recommend using version `0.3.1 <https://github.com/vyperlang/vyper/releases/tag/v0.3.1>`_ or higher. For more information, please see the Security Advisory `GHSA-5824-cm3x-3c38 <https://github.com/vyperlang/vyper/security/advisories/GHSA-5824-cm3x-3c38>`_.
 
 Date released: 2021-08-27
 
@@ -392,6 +394,7 @@ Special thanks to contributions from @skellet0r, @sambacha and @milancermak for
 
 v0.2.15
 *******
+⚠️ A critical security vulnerability has been discovered in this version and we strongly recommend using version `0.3.1 <https://github.com/vyperlang/vyper/releases/tag/v0.3.1>`_ or higher. For more information, please see the Security Advisory `GHSA-5824-cm3x-3c38 <https://github.com/vyperlang/vyper/security/advisories/GHSA-5824-cm3x-3c38>`_.
 
 Date released: 23-07-2021
 
diff --git a/vyper/semantics/analysis/local.py b/vyper/semantics/analysis/local.py
index c0c05325..c10df3b8 100644
--- a/vyper/semantics/analysis/local.py
+++ b/vyper/semantics/analysis/local.py
@@ -346,10 +346,11 @@ class FunctionNodeVisitor(VyperNodeVisitorBase):
                 raise IteratorException(
                     "Cannot iterate over the result of a function call", node.iter
                 )
-            validate_call_args(node.iter, (1, 2), kwargs=["bound"])
+            range_ = node.iter
+            validate_call_args(range_, (1, 2), kwargs=["bound"])
 
-            args = node.iter.args
-            kwargs = {s.arg: s.value for s in node.iter.keywords or []}
+            args = range_.args
+            kwargs = {s.arg: s.value for s in range_.keywords or []}
             if len(args) == 1:
                 # range(CONSTANT)
                 n = args[0]
@@ -371,6 +372,13 @@ class FunctionNodeVisitor(VyperNodeVisitorBase):
                     type_list = get_common_types(n, bound)
 
             else:
+                if range_.keywords:
+                    raise StructureException(
+                        "Keyword arguments are not supported for `range(N, M)` and"
+                        "`range(x, x + N)` expressions",
+                        range_.keywords[0],
+                    )
+
                 validate_expected_type(args[0], IntegerT.any())
                 type_list = get_common_types(*args)
                 if not isinstance(args[0], vy_ast.Constant):


Test patch:
diff --git a/tests/parser/syntax/test_for_range.py b/tests/parser/syntax/test_for_range.py
index b2a94910..e6f35c1d 100644
--- a/tests/parser/syntax/test_for_range.py
+++ b/tests/parser/syntax/test_for_range.py
@@ -12,7 +12,26 @@ def foo():
         pass
     """,
         StructureException,
-    )
+    ),
+    (
+        """
+@external
+def bar():
+    for i in range(1,2,bound=2):
+        pass
+    """,
+        StructureException,
+    ),
+    (
+        """
+@external
+def bar():
+    x:uint256 = 1
+    for i in range(x,x+1,bound=2):
+        pass
+    """,
+        StructureException,
+    ),
 ]