SafePath.test.mjs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* eslint-disable
  2. max-len,
  3. no-return-assign,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. import { assert, expect } from 'vitest'
  14. import sinon from 'sinon'
  15. const modulePath = '../../../../app/src/Features/Project/SafePath'
  16. describe('SafePath', function () {
  17. beforeEach(async function (ctx) {
  18. return (ctx.SafePath = (await import(modulePath)).default)
  19. })
  20. describe('isCleanFilename', function () {
  21. it('should accept a valid filename "main.tex"', function (ctx) {
  22. const result = ctx.SafePath.isCleanFilename('main.tex')
  23. return result.should.equal(true)
  24. })
  25. it('should not accept an empty filename', function (ctx) {
  26. const result = ctx.SafePath.isCleanFilename('')
  27. return result.should.equal(false)
  28. })
  29. it('should not accept / anywhere', function (ctx) {
  30. const result = ctx.SafePath.isCleanFilename('foo/bar')
  31. return result.should.equal(false)
  32. })
  33. it('should not accept .', function (ctx) {
  34. const result = ctx.SafePath.isCleanFilename('.')
  35. return result.should.equal(false)
  36. })
  37. it('should not accept ..', function (ctx) {
  38. const result = ctx.SafePath.isCleanFilename('..')
  39. return result.should.equal(false)
  40. })
  41. it('should not accept * anywhere', function (ctx) {
  42. const result = ctx.SafePath.isCleanFilename('foo*bar')
  43. return result.should.equal(false)
  44. })
  45. it('should not accept leading whitespace', function (ctx) {
  46. const result = ctx.SafePath.isCleanFilename(' foobar.tex')
  47. return result.should.equal(false)
  48. })
  49. it('should not accept trailing whitespace', function (ctx) {
  50. const result = ctx.SafePath.isCleanFilename('foobar.tex ')
  51. return result.should.equal(false)
  52. })
  53. it('should not accept leading and trailing whitespace', function (ctx) {
  54. const result = ctx.SafePath.isCleanFilename(' foobar.tex ')
  55. return result.should.equal(false)
  56. })
  57. it('should not accept control characters (0-31)', function (ctx) {
  58. const result = ctx.SafePath.isCleanFilename('foo\u0010bar')
  59. return result.should.equal(false)
  60. })
  61. it('should not accept control characters (127, delete)', function (ctx) {
  62. const result = ctx.SafePath.isCleanFilename('foo\u007fbar')
  63. return result.should.equal(false)
  64. })
  65. it('should not accept control characters (128-159)', function (ctx) {
  66. const result = ctx.SafePath.isCleanFilename('foo\u0080\u0090bar')
  67. return result.should.equal(false)
  68. })
  69. it('should not accept surrogate characters (128-159)', function (ctx) {
  70. const result = ctx.SafePath.isCleanFilename('foo\uD800\uDFFFbar')
  71. return result.should.equal(false)
  72. })
  73. it('should accept javascript property names', function (ctx) {
  74. const result = ctx.SafePath.isCleanFilename('prototype')
  75. return result.should.equal(true)
  76. })
  77. it('should accept javascript property names in the prototype', function (ctx) {
  78. const result = ctx.SafePath.isCleanFilename('hasOwnProperty')
  79. return result.should.equal(true)
  80. })
  81. // this test never worked correctly because the spaces are not replaced by underscores in isCleanFilename
  82. // it 'should not accept javascript property names resulting from substitutions', ->
  83. // result = @SafePath.isCleanFilename ' proto '
  84. // result.should.equal false
  85. // it 'should not accept a trailing .', ->
  86. // result = @SafePath.isCleanFilename 'hello.'
  87. // result.should.equal false
  88. it('should not accept \\', function (ctx) {
  89. const result = ctx.SafePath.isCleanFilename('foo\\bar')
  90. return result.should.equal(false)
  91. })
  92. it('should reject filenames regardless of order (/g) for bad characters', function (ctx) {
  93. const result1 = ctx.SafePath.isCleanFilename('foo*bar.tex') // * is not allowed
  94. const result2 = ctx.SafePath.isCleanFilename('*foobar.tex') // bad char location is before previous match
  95. return result1.should.equal(false) && result2.should.equal(false)
  96. })
  97. it('should reject filenames regardless of order (/g) for bad filenames', function (ctx) {
  98. const result1 = ctx.SafePath.isCleanFilename('foo ') // trailing space
  99. const result2 = ctx.SafePath.isCleanFilename(' foobar') // leading space, match location is before previous match
  100. return result1.should.equal(false) && result2.should.equal(false)
  101. })
  102. })
  103. describe('isCleanPath', function () {
  104. it('should accept a valid filename "main.tex"', function (ctx) {
  105. const result = ctx.SafePath.isCleanPath('main.tex')
  106. return result.should.equal(true)
  107. })
  108. it('should accept a valid path "foo/main.tex"', function (ctx) {
  109. const result = ctx.SafePath.isCleanPath('foo/main.tex')
  110. return result.should.equal(true)
  111. })
  112. it('should accept empty path elements', function (ctx) {
  113. const result = ctx.SafePath.isCleanPath('foo//main.tex')
  114. return result.should.equal(true)
  115. })
  116. it('should not accept an empty filename', function (ctx) {
  117. const result = ctx.SafePath.isCleanPath('foo/bar/')
  118. return result.should.equal(false)
  119. })
  120. it('should accept a path that starts with a slash', function (ctx) {
  121. const result = ctx.SafePath.isCleanPath('/etc/passwd')
  122. return result.should.equal(true)
  123. })
  124. it('should not accept a path that has an asterisk as the 0th element', function (ctx) {
  125. const result = ctx.SafePath.isCleanPath('*/foo/bar')
  126. return result.should.equal(false)
  127. })
  128. it('should not accept a path that has an asterisk as a middle element', function (ctx) {
  129. const result = ctx.SafePath.isCleanPath('foo/*/bar')
  130. return result.should.equal(false)
  131. })
  132. it('should not accept a path that has an asterisk as the filename', function (ctx) {
  133. const result = ctx.SafePath.isCleanPath('foo/bar/*')
  134. return result.should.equal(false)
  135. })
  136. it('should not accept a path that contains an asterisk in the 0th element', function (ctx) {
  137. const result = ctx.SafePath.isCleanPath('f*o/bar/baz')
  138. return result.should.equal(false)
  139. })
  140. it('should not accept a path that contains an asterisk in a middle element', function (ctx) {
  141. const result = ctx.SafePath.isCleanPath('foo/b*r/baz')
  142. return result.should.equal(false)
  143. })
  144. it('should not accept a path that contains an asterisk in the filename', function (ctx) {
  145. const result = ctx.SafePath.isCleanPath('foo/bar/b*z')
  146. return result.should.equal(false)
  147. })
  148. it('should not accept multiple problematic elements', function (ctx) {
  149. const result = ctx.SafePath.isCleanPath('f*o/b*r/b*z')
  150. return result.should.equal(false)
  151. })
  152. it('should not accept a problematic path with an empty element', function (ctx) {
  153. const result = ctx.SafePath.isCleanPath('foo//*/bar')
  154. return result.should.equal(false)
  155. })
  156. it('should not accept javascript property names', function (ctx) {
  157. const result = ctx.SafePath.isCleanPath('prototype')
  158. return result.should.equal(false)
  159. })
  160. it('should not accept javascript property names in the prototype', function (ctx) {
  161. const result = ctx.SafePath.isCleanPath('hasOwnProperty')
  162. return result.should.equal(false)
  163. })
  164. it('should not accept javascript property names resulting from substitutions', function (ctx) {
  165. const result = ctx.SafePath.isCleanPath(' proto ')
  166. return result.should.equal(false)
  167. })
  168. })
  169. describe('isAllowedLength', function () {
  170. it('should accept a valid path "main.tex"', function (ctx) {
  171. const result = ctx.SafePath.isAllowedLength('main.tex')
  172. return result.should.equal(true)
  173. })
  174. it('should not accept an extremely long path', function (ctx) {
  175. const longPath = new Array(1000).join('/subdir') + '/main.tex'
  176. const result = ctx.SafePath.isAllowedLength(longPath)
  177. return result.should.equal(false)
  178. })
  179. it('should not accept an empty path', function (ctx) {
  180. const result = ctx.SafePath.isAllowedLength('')
  181. return result.should.equal(false)
  182. })
  183. })
  184. describe('clean', function () {
  185. it('should not modify a valid filename', function (ctx) {
  186. const result = ctx.SafePath.clean('main.tex')
  187. return result.should.equal('main.tex')
  188. })
  189. it('should replace invalid characters with _', function (ctx) {
  190. const result = ctx.SafePath.clean('foo/bar*/main.tex')
  191. return result.should.equal('foo_bar__main.tex')
  192. })
  193. it('should replace "." with "_"', function (ctx) {
  194. const result = ctx.SafePath.clean('.')
  195. return result.should.equal('_')
  196. })
  197. it('should replace ".." with "__"', function (ctx) {
  198. const result = ctx.SafePath.clean('..')
  199. return result.should.equal('__')
  200. })
  201. it('should replace a single trailing space with _', function (ctx) {
  202. const result = ctx.SafePath.clean('foo ')
  203. return result.should.equal('foo_')
  204. })
  205. it('should replace a multiple trailing spaces with ___', function (ctx) {
  206. const result = ctx.SafePath.clean('foo ')
  207. return result.should.equal('foo__')
  208. })
  209. it('should replace a single leading space with _', function (ctx) {
  210. const result = ctx.SafePath.clean(' foo')
  211. return result.should.equal('_foo')
  212. })
  213. it('should replace a multiple leading spaces with ___', function (ctx) {
  214. const result = ctx.SafePath.clean(' foo')
  215. return result.should.equal('__foo')
  216. })
  217. it('should prefix javascript property names with @', function (ctx) {
  218. const result = ctx.SafePath.clean('prototype')
  219. return result.should.equal('@prototype')
  220. })
  221. it('should prefix javascript property names in the prototype with @', function (ctx) {
  222. const result = ctx.SafePath.clean('hasOwnProperty')
  223. return result.should.equal('@hasOwnProperty')
  224. })
  225. })
  226. })