0

Is Node decodeURIComponent idempotent?

Does...

decodeURIComponent(x) === decodeURIComponent(decodeURIComponent(x))

for any and all x?

If not, is there an alternative that is idempotent? Was trying to think through if this was possible myself.

lmonninger
  • 831
  • 3
  • 13
  • It can't be. You can apply it three times on `%252525XX` until you get to `%XX`, and next time you'll get `URI malformed` – CherryDT Oct 07 '21 at 15:22
  • 1
    But that you even have this problem is an indication for a much bigger (and potentially security-relevant) problem elsewhere in your code, and _that's_ what you should fix. – CherryDT Oct 07 '21 at 15:24
  • I don't have issues in an application. I actually phrased the question the way I did because I knew it would attract attention haha. (I'm actually interested in trying to put together a different grammar for escaping.) – lmonninger Oct 07 '21 at 15:26
  • Then it's not a practical question and thereby off-topic for Stack Overflow. – CherryDT Oct 07 '21 at 15:27
  • I thought you would say that. Which is why is asked a practical version of an adjacent question. – lmonninger Oct 07 '21 at 15:28
  • The question is still the question. – lmonninger Oct 07 '21 at 15:28
  • See [here](https://meta.stackoverflow.com/questions/411999/how-can-i-make-my-very-downvoted-question-more-well-received) as for why it's still probably not a good idea to ask it ^^ – CherryDT Oct 07 '21 at 15:31

2 Answers2

1

No

> encodeURIComponent('%')
'%25'
> encodeURIComponent(encodeURIComponent('%'))
'%2525'

> decodeURIComponent('%2525')
'%25'
> decodeURIComponent(decodeURIComponent('%2525'))
'%'

> decodeURIComponent('%2525') === decodeURIComponent(decodeURIComponent('%2525'))
false
DemiPixel
  • 1,768
  • 11
  • 19
1

No. If the string decodes to a new sequence which itself can be interpreted as an encoded URI component, then it can be decoded again to a different string:

const x = '%2521';
console.log(decodeURIComponent(x), decodeURIComponent(decodeURIComponent(x)));

%2521%21!

Any given string is either encoded in a specific format or is plain text. You cannot guess what it is supposed to be. %21 could either be the plaintext string "%21", or a URL-encoded string representing "!". You need to know which it's supposed to be and interpreted it accordingly. That generally goes for any and all text encoding formats.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Do you know of a grammar that would be? – lmonninger Oct 07 '21 at 15:24
  • 1
    That's not really a practical question, is it? – deceze Oct 07 '21 at 15:25
  • 1
    Without limiting what values the encoding can represent, there can _never_ be such a solution - it's not possible. – CherryDT Oct 07 '21 at 15:25
  • @CherryDT But, if I did, say by limiting a string to 360 chars, it would be? – lmonninger Oct 07 '21 at 15:27
  • @lmonninger only if the encoded format would be mutually exclusive in its range of possible values with the decoded format - in your example, if any encoded value would be padded to 361 characters minimum (which wouldn't be very useful I think) – CherryDT Oct 07 '21 at 15:29
  • 1
    @Imonninger You would need to limit the *kinds* of characters the encoding can represent, not the length. E.g. if you forbade the use of the character "%", then no `%..` sequence could ever decode to another `%..` sequence, and thereby not be recursively decodable. But disallowing the use of specific characters makes this a very impractical encoding format. – deceze Oct 07 '21 at 15:31
  • You mean because it's too short or because it adds to length of the string? If the former, I could just chunk it. If the latter, I wouldn't be too worried in JS. – lmonninger Oct 07 '21 at 15:31
  • @CherryDT Know any papers? I only have a passing familiarity with idempotent structures vis CRDTs. – lmonninger Oct 07 '21 at 15:32
  • 1
    I believe the correct place to ask this whole question (and I mean the _actual_ question, not the XY problem you intentionally created here) would be https://cs.stackexchange.com/ :) – CherryDT Oct 07 '21 at 15:36
  • Alright, the folks over here are usually a bit more helpful. But, thanks! Maybe I'll see you over there. You think I should close the actual question? Or, keep it in case someone else is looking? – lmonninger Oct 07 '21 at 15:38