Not reporting against 8.x because I believe this whole thing doesn't apply to it, correct me if I'm wrong.

The 'node/%node' route doesn't check the value/type of the path argument. So if node/3165341 is a valid node, the path node/3165341.test.1234.lol will also load the same node.

Example, these two links load the same node:
https://www.acquia.com/node/3165341
https://www.acquia.com/node/3165341.test.1234.lol

This is because %node (node_load() --> node_load_multiple()) uses the IN comparison, and MySQL will cast comparisons.

As an example, take this query generated by node_load() (I modified the columns selected for clarity):

mysql> SELECT revision.vid AS vid, base.uid AS uid, revision.log AS log, revision.status AS status, revision.comment AS comment, revision.promote AS promote, revision.sticky AS sticky, base.nid AS nid, base.type AS type, base.language AS language, base.created AS created, base.changed AS changed, base.tnid AS tnid, base.translate AS translate, revision.timestamp AS revision_timestamp, revision.uid AS revision_uid FROM  node base INNER JOIN node_revision revision ON revision.vid = base.vid WHERE  (base.nid IN  ('194.test2'));
+-----+-----+-----+--------+---------+---------+--------+-----+-------------+----------+------------+------------+------+-----------+--------------------+--------------+
| vid | uid | log | status | comment | promote | sticky | nid | type        | language | created    | changed    | tnid | translate | revision_timestamp | revision_uid |
+-----+-----+-----+--------+---------+---------+--------+-----+-------------+----------+------------+------------+------+-----------+--------------------+--------------+
| 258 |  25 |     |      1 |       1 |       0 |      0 | 194 | publication | und      | 1409003246 | 1429300032 |    0 |         0 |         1429300032 |           32 |
+-----+-----+-----+--------+---------+---------+--------+-----+-------------+----------+------------+------------+------+-----------+--------------------+--------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------+
| Level   | Code | Message                                       |
+---------+------+-----------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '194.test2' |
+---------+------+-----------------------------------------------+
1 row in set (0.00 sec)

I believe the right fix would be to check if the values passed to node_load() are numeric, and throw an error (404?) otherwise.

Comments

entendu’s picture

Issue summary: View changes
cilefen’s picture

Did you test on 8.0.x? https://simplytest.me/

pwolanin’s picture

Yes, this bug has been around for lots of numeric IDs in 7 forever. Please search for existing issues.

It's not limited to nodes, but affects every entity pretty much.

I think you are actually mistaking the cause - look at:
https://api.drupal.org/api/drupal/includes%21entity.inc/function/DrupalD...

That calls intval() which is casting:

php > echo intval('1.a1');
1

In 8, at least some routes use a regex to validate the input, but not nodes:
https://api.drupal.org/api/drupal/core%21modules%21node%21src%21Entity%2...

I'm not sure where 8 is filtering or validating.

entendu’s picture

Ah, yes this has a fix in #1003788. Marking dupe.

pwolanin’s picture

Status: Closed (duplicate) » Active

Thanks for searching, but that's not actually a duplicate of this bug

David_Rothstein’s picture

Status: Active » Postponed (maintainer needs more info)

I'm pretty sure the issue @entendu linked to actually did fix this in Drupal 7.37. If you go to node/1.test on Drupal 7.36 you see node 1 (on MySQL), but in Drupal 7.37 and higher you get page not found.

If this isn't the same issue, then what's the remaining work to do here?