a weird bug
Thank you very much Xiao Zhao for giving me feedback on this bug 🙌🙌
Test your Javascript basics before you start explaining. Just looking at the code, what do you think it will output? The answer will be revealed later.
'Hello'.replace('ello', '#$&%')
In other words, one day I suddenly received an email, a classmate told me that my site was bombed, and I was so frightened that I suddenly rolled over from the bed - I felt that the charging cable was a bit strangling and I turned back again...
After a wave of detailed inquiries, I learned that it is my self-built blog site, which is the one I am currently writing an article on. It will display a part of the code at the bottom of the page on a certain page. like this:
Feeling bad all of a sudden - the dead bug came back to attack me all of a sudden. .
This problem actually appeared before, but I fixed it later. Today it appeared again, and I quickly reproduced it, but I found that I had no problem with my own access. I finally found that it was a problem with the rendering script of my server. . So if you go directly to the site and browse the article, you won't encounter it. Most of the time I thought it was fixed. The way to reproduce is also very simple: you have to go directly to a certain blog post from a certain link to trigger it, which is very interesting! Basically, it can be explained that it is triggered due to data reasons.
Because my server-side rendering is written in Express, not a ready-made framework, there may be problems in some places and it is normal. After a wave of exploration, a block of code is located, and the debugging results are very strange. Roughly:
// 我的页面模板
const template = fn();
// 渲染出来的页面样式
const css = fn();
// 当前访问页面所用到的 React state
const state = fn();
// 将所有内容由不同的锚点定位,替换到模板中去,每个锚点有且只有一个
const page = template
.replace('css anchor', css)
.replace('state anchor', state)
console.log(template.includes('state anchor'))
// true
console.log(page.includes('state anchor'))
// true
console.log(state.includes('state anchor'))
// false
Heck! Do the traces in the page still exist after being replaced? Then I added another test later:
const page = template
.replace('css anchor', css)
.replace('state anchor', state)
.replace('state anchor', 'f*** me')
console.log(template.includes('state anchor'))
// true
console.log(page.includes('state anchor'))
// false
console.log(state.includes('state anchor'))
// false
It's weird, I replaced it again and it was comfortable and gone. . Then I followed the position where the trace was replaced, and finally found it in this position in a certain piece of text:
" Use <Space-E> to open explorer
" Using Coc-explorer
noremap <space>e :CocCommand explorer<CR>
" Close Coc-explorer if it is the only window
autocmd BufEnter * if (&ft == 'coc-explorer' && winnr("$") == 1) | q | endif
This is my previous article about Vim and Coc. Focus on this winnr("$")
, because the page is escaped during rendering, the data obtained is actually "$"
. That is, two quotation marks are replaced with "
now. And what I used above is replace to replace the content. And guess what in the replacement text of the replace method? $&
represents the matching content itself! So my actual replacement would be: winnr("f*** mequot;)
...
Let's start explaining~
In fact, the replace function of strings in Javascript has a specific escape character (variable name) when the incoming parameter is a string. For example above, if you write '$&'
then it will replace your search character in it. There are others like this:
$$
是插入一个 "$"。
$&
是插入匹配的子串。
$`
是插入当前匹配的子串左边的内容。
$'
是插入当前匹配的子串右边的内容。
$n
假如第一个参数是 RegExp 对象,并且 n 是个小于 100 的非负整数,
那么插入第 n 个括号匹配的字符串。提示:索引是从 1 开始。如果不存在第 n 个分组,
那么将会把匹配到到内容替换为字面量。比如不存在第 3 个分组,就会用“$3”替换匹配到的内容。
$<Name>
这里 Name 是一个分组名称。如果在正则表达式中并不存在分组(或者没有匹配),
这个变量将被处理为空字符串。只有在支持命名分组捕获的浏览器中才能使用。
Of course, you can also pass the function in without passing the string. This is not expanded, you can go here for a closer look: MDN - String.prototype.replace()
Switching to the actual situation is because the anchor point of the state I insert is a script tag, so the content of Html is truncated. It's a bit similar to the principle of cross-site attack (XSS), so it's just a broken code block at the bottom of the page and the display of the text is normal.
It's easy to fix if you know what the problem is! Just write a replacement function that won't be escaped by any string.
You can think about how to write it yourself 🤣
Then there is the opening question, do you know what the answer is now?
'Hello'.replace('ello', '#$&%')
// 'H#ello%'
Alright, that's it for today~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。