/pypy/translator/sandbox/test/test_sandbox.py

https://bitbucket.org/pypy/pypy/ · Python · 302 lines · 268 code · 34 blank · 0 comment · 13 complexity · 88d2b9f5bb6474d7991f3904b884cf47 MD5 · raw file

  1. import py
  2. import sys, os, time
  3. import struct
  4. import subprocess
  5. from pypy.rpython.lltypesystem import rffi
  6. from pypy.translator.interactive import Translation
  7. from pypy.translator.sandbox.sandlib import read_message, write_message
  8. from pypy.translator.sandbox.sandlib import write_exception
  9. def expect(f, g, fnname, args, result, resulttype=None):
  10. msg = read_message(f, timeout=10.0)
  11. assert msg == fnname
  12. msg = read_message(f, timeout=10.0)
  13. assert msg == args
  14. if isinstance(result, Exception):
  15. write_exception(g, result)
  16. else:
  17. write_message(g, 0)
  18. write_message(g, result, resulttype)
  19. g.flush()
  20. def compile(f, gc='ref'):
  21. t = Translation(f, backend='c', standalone=True, sandbox=True, gc=gc)
  22. return str(t.compile())
  23. def test_open_dup():
  24. def entry_point(argv):
  25. fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
  26. assert fd == 77
  27. fd2 = os.dup(fd)
  28. assert fd2 == 78
  29. return 0
  30. exe = compile(entry_point)
  31. g, f = os.popen2(exe, "t", 0)
  32. expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77)
  33. expect(f, g, "ll_os.ll_os_dup", (77,), 78)
  34. g.close()
  35. tail = f.read()
  36. f.close()
  37. assert tail == ""
  38. def test_read_write():
  39. def entry_point(argv):
  40. fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
  41. assert fd == 77
  42. res = os.read(fd, 123)
  43. assert res == "he\x00llo"
  44. count = os.write(fd, "world\x00!\x00")
  45. assert count == 42
  46. os.close(fd)
  47. return 0
  48. exe = compile(entry_point)
  49. g, f = os.popen2(exe, "t", 0)
  50. expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77)
  51. expect(f, g, "ll_os.ll_os_read", (77, 123), "he\x00llo")
  52. expect(f, g, "ll_os.ll_os_write", (77, "world\x00!\x00"), 42)
  53. expect(f, g, "ll_os.ll_os_close", (77,), None)
  54. g.close()
  55. tail = f.read()
  56. f.close()
  57. assert tail == ""
  58. def test_dup2_access():
  59. def entry_point(argv):
  60. os.dup2(34, 56)
  61. y = os.access("spam", 77)
  62. return 1 - y
  63. exe = compile(entry_point)
  64. g, f = os.popen2(exe, "t", 0)
  65. expect(f, g, "ll_os.ll_os_dup2", (34, 56), None)
  66. expect(f, g, "ll_os.ll_os_access", ("spam", 77), True)
  67. g.close()
  68. tail = f.read()
  69. f.close()
  70. assert tail == ""
  71. def test_stat_ftruncate():
  72. from pypy.translator.sandbox.sandlib import RESULTTYPE_STATRESULT
  73. from pypy.rlib.rarithmetic import r_longlong
  74. r0x12380000007 = r_longlong(0x12380000007)
  75. def entry_point(argv):
  76. st = os.stat("somewhere")
  77. os.ftruncate(st.st_mode, st.st_size) # nonsense, just to see outside
  78. return 0
  79. exe = compile(entry_point)
  80. g, f = os.popen2(exe, "t", 0)
  81. st = os.stat_result((55, 0, 0, 0, 0, 0, 0x12380000007, 0, 0, 0))
  82. expect(f, g, "ll_os.ll_os_stat", ("somewhere",), st,
  83. resulttype = RESULTTYPE_STATRESULT)
  84. expect(f, g, "ll_os.ll_os_ftruncate", (55, 0x12380000007), None)
  85. g.close()
  86. tail = f.read()
  87. f.close()
  88. assert tail == ""
  89. def test_time():
  90. def entry_point(argv):
  91. t = time.time()
  92. os.dup(int(t*1000))
  93. return 0
  94. exe = compile(entry_point)
  95. g, f = os.popen2(exe, "t", 0)
  96. expect(f, g, "ll_time.ll_time_time", (), 3.141592)
  97. expect(f, g, "ll_os.ll_os_dup", (3141,), 3)
  98. g.close()
  99. tail = f.read()
  100. f.close()
  101. assert tail == ""
  102. def test_oserror():
  103. def entry_point(argv):
  104. try:
  105. os.stat("somewhere")
  106. except OSError, e:
  107. os.close(e.errno) # nonsense, just to see outside
  108. return 0
  109. exe = compile(entry_point)
  110. g, f = os.popen2(exe, "t", 0)
  111. expect(f, g, "ll_os.ll_os_stat", ("somewhere",), OSError(6321, "egg"))
  112. expect(f, g, "ll_os.ll_os_close", (6321,), None)
  113. g.close()
  114. tail = f.read()
  115. f.close()
  116. assert tail == ""
  117. def test_hybrid_gc():
  118. def entry_point(argv):
  119. l = []
  120. for i in range(int(argv[1])):
  121. l.append("x" * int(argv[2]))
  122. return int(len(l) > 1000)
  123. exe = compile(entry_point, gc='hybrid')
  124. pipe = subprocess.Popen([exe, '10', '10000'], stdout=subprocess.PIPE,
  125. stdin=subprocess.PIPE)
  126. g = pipe.stdin
  127. f = pipe.stdout
  128. expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GENERATIONGC_NURSERY",), None)
  129. if sys.platform.startswith('linux'): # on Mac, uses another (sandboxsafe) approach
  130. expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420),
  131. OSError(5232, "xyz"))
  132. expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_DEBUG",), None)
  133. g.close()
  134. tail = f.read()
  135. f.close()
  136. assert tail == ""
  137. rescode = pipe.wait()
  138. assert rescode == 0
  139. def test_segfault_1():
  140. class A:
  141. def __init__(self, m):
  142. self.m = m
  143. def g(m):
  144. if m < 10:
  145. return None
  146. return A(m)
  147. def entry_point(argv):
  148. x = g(len(argv))
  149. return int(x.m)
  150. exe = compile(entry_point)
  151. g, f, e = os.popen3(exe, "t", 0)
  152. g.close()
  153. tail = f.read()
  154. f.close()
  155. assert tail == ""
  156. errors = e.read()
  157. e.close()
  158. assert 'Invalid RPython operation' in errors
  159. def test_segfault_2():
  160. py.test.skip("hum, this is one example, but we need to be very careful")
  161. class Base:
  162. pass
  163. class A(Base):
  164. def __init__(self, m):
  165. self.m = m
  166. def getm(self):
  167. return self.m
  168. class B(Base):
  169. def __init__(self, a):
  170. self.a = a
  171. def g(m):
  172. a = A(m)
  173. if m < 10:
  174. a = B(a)
  175. return a
  176. def entry_point(argv):
  177. x = g(len(argv))
  178. os.write(2, str(x.getm()))
  179. return 0
  180. exe = compile(entry_point)
  181. g, f, e = os.popen3(exe, "t", 0)
  182. g.close()
  183. tail = f.read(23)
  184. f.close()
  185. assert tail == "" # and not ll_os.ll_os_write
  186. errors = e.read()
  187. e.close()
  188. assert '...think what kind of errors to get...' in errors
  189. def test_safe_alloc():
  190. from pypy.rlib.rmmap import alloc, free
  191. def entry_point(argv):
  192. one = alloc(1024)
  193. free(one, 1024)
  194. return 0
  195. exe = compile(entry_point)
  196. pipe = subprocess.Popen([exe], stdout=subprocess.PIPE,
  197. stdin=subprocess.PIPE)
  198. g = pipe.stdin
  199. f = pipe.stdout
  200. g.close()
  201. tail = f.read()
  202. f.close()
  203. assert tail == ""
  204. rescode = pipe.wait()
  205. assert rescode == 0
  206. def test_unsafe_mmap():
  207. py.test.skip("Since this stuff is unimplemented, it won't work anyway "
  208. "however, the day it starts working, it should pass test")
  209. from pypy.rlib.rmmap import mmap
  210. def entry_point(argv):
  211. try:
  212. res = mmap(0, 1024)
  213. except OSError:
  214. return 0
  215. return 1
  216. exe = compile(entry_point)
  217. pipe = subprocess.Popen([exe], stdout=subprocess.PIPE,
  218. stdin=subprocess.PIPE)
  219. g = pipe.stdin
  220. f = pipe.stdout
  221. expect(f, g, "mmap", ARGS, OSError(1, "xyz"))
  222. g.close()
  223. tail = f.read()
  224. f.close()
  225. assert tail == ""
  226. rescode = pipe.wait()
  227. assert rescode == 0
  228. class TestPrintedResults:
  229. def run(self, entry_point, args, expected):
  230. exe = compile(entry_point)
  231. from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc
  232. proc = SimpleIOSandboxedProc([exe] + args)
  233. output, error = proc.communicate()
  234. assert error == ''
  235. assert output == expected
  236. def test_safefuncs(self):
  237. import math
  238. def entry_point(argv):
  239. a = float(argv[1])
  240. print int(math.floor(a - 0.2)),
  241. print int(math.ceil(a)),
  242. print int(100.0 * math.sin(a)),
  243. mantissa, exponent = math.frexp(a)
  244. print int(100.0 * mantissa), exponent,
  245. fracpart, intpart = math.modf(a)
  246. print int(100.0 * fracpart), int(intpart),
  247. print
  248. return 0
  249. self.run(entry_point, ["3.011"], "2 4 13 75 2 1 3\n")
  250. def test_safefuncs_exception(self):
  251. import math
  252. def entry_point(argv):
  253. a = float(argv[1])
  254. x = math.log(a)
  255. print int(x * 100.0)
  256. try:
  257. math.log(-a)
  258. except ValueError:
  259. print 'as expected, got a ValueError'
  260. else:
  261. print 'did not get a ValueError!'
  262. return 0
  263. self.run(entry_point, ["3.011"], "110\nas expected, got a ValueError\n")
  264. def test_os_path_safe(self):
  265. def entry_point(argv):
  266. print os.path.join('tmp', argv[1])
  267. return 0
  268. self.run(entry_point, ["spam"], os.path.join("tmp", "spam")+'\n')