skip to main content
research-article
Free Access

A Principled Approach to Selective Context Sensitivity for Pointer Analysis

Published:19 May 2020Publication History
Skip Abstract Section

Abstract

Context sensitivity is an essential technique for ensuring high precision in static analyses. It has been observed that applying context sensitivity partially, only on a select subset of the methods, can improve the balance between analysis precision and speed. However, existing techniques are based on heuristics that do not provide much insight into what characterizes this method subset. In this work, we present a more principled approach for identifying precision-critical methods, based on general patterns of value flows that explain where most of the imprecision arises in context-insensitive pointer analysis. Using this theoretical foundation, we present an efficient algorithm, ZIPPER, to recognize these flow patterns in a given program and employ context sensitivity accordingly. We also present a variant, ZIPPERe, that additionally takes into account which methods are disproportionally costly to analyze with context sensitivity.

Our experimental results on standard benchmark and real-world Java programs show that ZIPPER preserves effectively all of the precision (98.8%) of a highly precise conventional context-sensitive pointer analysis (2-object-sensitive with a context-sensitive heap, 2obj for short), with a substantial speedup (on average, 3.4× and up to 9.4×), and that ZIPPERe preserves 94.7% of the precision of 2obj, with an order-of-magnitude speedup (on average, 25.5× and up to 88×). In addition, for 10 programs that cannot be analyzed by 2obj within a three-hour time limit, on average ZIPPERe can guide 2obj to finish analyzing them in less than 11 minutes with high precision compared to context-insensitive and introspective context-sensitive analyses.

References

  1. Lars Ole Andersen. 1994. Program Analysis and Specialization for the C Programming Language. Ph.D. Dissertation. University of CopGoogle ScholarGoogle Scholar
  2. Steven Arzt, Siegfried Rasthofer, Christian Fritz, Eric Bodden, Alexandre Bartel, Jacques Klein, Yves Le Traon, Damien Octeau, and Patrick D. McDaniel. 2014. FlowDroid: Precise context, flow, field, object-sensitive, and lifecycle-aware taint analysis for Android apps. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’14), Michael F. P. O’Boyle and Keshav Pingali (Eds.). ACM, 259--269. DOI:https://doi.org/10.1145/2594291.2594299Google ScholarGoogle Scholar
  3. Stephen M. Blackburn, Robin Garner, Chris Hoffmann, Asjad M. Khan, Kathryn S. McKinley, Rotem Bentzur, Amer Diwan, Daniel Feinberg, Daniel Frampton, Samuel Z. Guyer, Martin Hirzel, Antony L. Hosking, Maria Jump, Han Bok Lee, J. Eliot B. Moss, Aashish Phansalkar, Darko Stefanovic, Thomas VanDrunen, Daniel von Dincklage, and Ben Wiedermann. 2006. The DaCapo benchmarks: Java benchmarking development and analysis. In Proceedings of the 21st ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA’06), Peri L. Tarr and William R. Cook (Eds.). ACM, 169--190. DOI:https://doi.org/10.1145/1167473.1167488Google ScholarGoogle ScholarDigital LibraryDigital Library
  4. Martin Bravenboer and Yannis Smaragdakis. 2009. Strictly declarative specification of sophisticated points-to analyses. In Proceedings of the 24th ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA’09), Shail Arora and Gary T. Leavens (Eds.). ACM, 243--262. DOI:https://doi.org/10.1145/1640089.1640108Google ScholarGoogle ScholarDigital LibraryDigital Library
  5. Satish Chandra, Stephen J. Fink, and Manu Sridharan. 2009. Snugglebug: A powerful approach to weakest preconditions. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’09), Michael Hind and Amer Diwan (Eds.). ACM, 363--374. DOI:https://doi.org/10.1145/1542476.1542517Google ScholarGoogle ScholarDigital LibraryDigital Library
  6. David R. Chase, Mark N. Wegman, and F. Kenneth Zadeck. 1990. Analysis of pointers and structures. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’90), Bernard N. Fischer (Ed.). ACM, 296--310. DOI:https://doi.org/10.1145/93542.93585Google ScholarGoogle Scholar
  7. Stephen J. Fink, Eran Yahav, Nurit Dor, G. Ramalingam, and Emmanuel Geay. 2008. Effective typestate verification in the presence of aliasing. ACM Trans. Softw. Eng. Methodol. 17, 2 (2008), 9:1–9:34. DOI:https://doi.org/10.1145/1348250.1348255Google ScholarGoogle ScholarDigital LibraryDigital Library
  8. Michael I. Gordon, Deokhwan Kim, Jeff H. Perkins, Limei Gilham, Nguyen Nguyen, and Martin C. Rinard. 2015. Information flow analysis of Android applications in DroidSafe. In Proceedings of the 22nd Network and Distributed System Security Symposium (NDSS’15). The Internet Society. Retrieved from https://www.ndss-symposium.org/ndss2015/information-flow-analysis-android-applications-droidsafe.Google ScholarGoogle Scholar
  9. Neville Grech and Yannis Smaragdakis. 2017. P/Taint: Unified points-to and taint analysis. PACMPL 1, OOPSLA (2017), 102:1–102:28. DOI:https://doi.org/10.1145/3133926Google ScholarGoogle Scholar
  10. Behnaz Hassanshahi, Raghavendra Kagalavadi Ramesh, Padmanabhan Krishnan, Bernhard Scholz, and Yi Lu. 2017. An efficient tunable selective points-to analysis for large codebases. In Proceedings of the 6th ACM SIGPLAN International Workshop on State Of the Art in Program Analysis ([email protected]’17), Karim Ali and Cristina Cifuentes (Eds.). ACM, 13--18. DOI:https://doi.org/10.1145/3088515.3088519Google ScholarGoogle ScholarDigital LibraryDigital Library
  11. Michael Hind. 2001. Pointer analysis: Haven’t we solved this problem yet? In Proceedings of the ACM SIGPLAN-SIGSOFT Workshop on Program Analysis For Software Tools and Engineering (PASTE’01), John Field and Gregor Snelting (Eds.). ACM, 54--61. DOI:https://doi.org/10.1145/379605.379665Google ScholarGoogle ScholarDigital LibraryDigital Library
  12. Minseok Jeon, Sehun Jeong, Sungdeok Cha, and Hakjoo Oh. 2019. A machine-learning algorithm with disjunctive model for data-driven program analysis. ACM Trans. Program. Lang. Syst. 41, 2 (2019), 13:1–13:41. DOI:https://doi.org/10.1145/3293607Google ScholarGoogle ScholarDigital LibraryDigital Library
  13. Minseok Jeon, Sehun Jeong, and Hakjoo Oh. 2018. Precise and scalable points-to analysis via data-driven context tunneling. Proc. ACM Program. Lang. 2, OOPSLA, Article 140 (Oct. 2018), 29 pages. DOI:https://doi.org/10.1145/3276510Google ScholarGoogle ScholarDigital LibraryDigital Library
  14. Sehun Jeong, Minseok Jeon, Sung Deok Cha, and Hakjoo Oh. 2017. Data-driven context-sensitivity for points-to analysis. PACMPL 1, OOPSLA (2017), 100:1–100:28. DOI:https://doi.org/10.1145/3133924Google ScholarGoogle Scholar
  15. Vini Kanvar and Uday P. Khedker. 2016. Heap abstractions for static analysis. ACM Comput. Surv. 49, 2, Article 29 (June 2016), 47 pages. DOI:https://doi.org/10.1145/2931098Google ScholarGoogle Scholar
  16. George Kastrinis and Yannis Smaragdakis. 2013. Hybrid context-sensitivity for points-to analysis. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’13), Hans-Juergen Boehm and Cormac Flanagan (Eds.). ACM, 423--434. DOI:https://doi.org/10.1145/2462156.2462191Google ScholarGoogle ScholarDigital LibraryDigital Library
  17. Ondrej Lhoták and Laurie J. Hendren. 2003. Scaling Java points-to analysis using SPARK. In Proceedings of the 12th International Conference on Compiler Construction (CC’03), Held as Part of the Joint European Conferences on Theory and Practice of Software (ETAPS’03) (Lecture Notes in Computer Science), Görel Hedin (Ed.), Vol. 2622. Springer, 153--169. DOI:https://doi.org/10.1007/3-540-36579-6_12Google ScholarGoogle Scholar
  18. Ondrej Lhoták and Laurie J. Hendren. 2006. Context-sensitive points-to analysis: Is it worth it? In Proceedings of the 15th International Conference on Compiler Construction (CC’06), Held as Part of the Joint European Conferences on Theory and Practice of Software, (ETAPS’06) (Lecture Notes in Computer Science), Alan Mycroft and Andreas Zeller (Eds.), Vol. 3923. Springer, 47--64. DOI:https://doi.org/10.1007/11688839_5Google ScholarGoogle Scholar
  19. Lian Li, Cristina Cifuentes, and Nathan Keynes. 2011. Boosting the performance of flow-sensitive points-to analysis using value flow. In Proceedings of the 19th ACM SIGSOFT Symposium and the 13th European Conference on Foundations of Software Engineering (ESEC/FSE’11). ACM, New York, NY, 343--353. DOI:https://doi.org/10.1145/2025113.2025160Google ScholarGoogle ScholarDigital LibraryDigital Library
  20. Yue Li, Tian Tan, Anders Møller, and Yannis Smaragdakis. 2018a. Precision-guided context sensitivity for pointer analysis. Proc. ACM Program. Lang. 2, OOPSLA, Article 141 (Oct. 2018), 29 pages. DOI:https://doi.org/10.1145/3276511Google ScholarGoogle ScholarDigital LibraryDigital Library
  21. Yue Li, Tian Tan, Anders Møller, and Yannis Smaragdakis. 2018b. Scalability-first pointer analysis with self-tuning context-sensitivity. In Proceedings of the 12th Joint Meeting of the European Software Engineering Conference and the ACM SIGSOFT Symposium on the Foundations of Software Engineering (ESEC/FSE’18). ACM, 129--140. DOI:https://doi.org/10.1145/3236024.3236041Google ScholarGoogle ScholarDigital LibraryDigital Library
  22. Yue Li, Tian Tan, Yifei Zhang, and Jingling Xue. 2016. Program tailoring: Slicing by sequential criteria. In Proceedings of the 30th European Conference on Object-Oriented Programming (ECOOP’16) (LIPIcs), Shriram Krishnamurthi and Benjamin S. Lerner (Eds.), Vol. 56. Schloss Dagstuhl - Leibniz-Zentrum fuer Informatik, 15:1–15:27. DOI:https://doi.org/10.4230/LIPIcs.ECOOP.2016.15Google ScholarGoogle Scholar
  23. Benjamin Livshits and Monica S. Lam. 2005. Finding security vulnerabilities in Java applications with static analysis. In Proceedings of the 14th USENIX Security Symposium, Patrick D. McDaniel (Ed.). USENIX Association.Google ScholarGoogle ScholarDigital LibraryDigital Library
  24. Ana Milanova, Atanas Rountev, and Barbara G. Ryder. 2002. Parameterized object sensitivity for points-to and side-effect analyses for Java. In Proceedings of the International Symposium on Software Testing and Analysis (ISSTA’02), Phyllis G. Frankl (Ed.). ACM, 1--11. DOI:https://doi.org/10.1145/566172.566174Google ScholarGoogle Scholar
  25. Ana Milanova, Atanas Rountev, and Barbara G. Ryder. 2005. Parameterized object sensitivity for points-to analysis for Java. ACM Trans. Softw. Eng. Methodol. 14, 1 (2005), 1--41. DOI:https://doi.org/10.1145/1044834.1044835Google ScholarGoogle ScholarDigital LibraryDigital Library
  26. Mayur Naik, Alex Aiken, and John Whaley. 2006. Effective static race detection for Java. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation, Michael I. Schwartzbach and Thomas Ball (Eds.). ACM, 308--319. DOI:https://doi.org/10.1145/1133981.1134018Google ScholarGoogle ScholarDigital LibraryDigital Library
  27. Mayur Naik, Chang-Seo Park, Koushik Sen, and David Gay. 2009. Effective static deadlock detection. In Proceedings of the 31st International Conference on Software Engineering (ICSE’09). IEEE, 386--396. DOI:https://doi.org/10.1109/ICSE.2009.5070538Google ScholarGoogle ScholarDigital LibraryDigital Library
  28. Hakjoo Oh, Wonchan Lee, Kihong Heo, Hongseok Yang, and Kwangkeun Yi. 2014. Selective context-sensitivity guided by impact pre-analysis. In Proceedings of the 35th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’14). ACM, New York, NY, 475--484. DOI:https://doi.org/10.1145/2594291.2594318Google ScholarGoogle ScholarDigital LibraryDigital Library
  29. Michael Pradel, Ciera Jaspan, Jonathan Aldrich, and Thomas R. Gross. 2012. Statically checking API protocol conformance with mined multi-object specifications. In Proceedings of the 34th International Conference on Software Engineering (ICSE’12), Martin Glinz, Gail C. Murphy, and Mauro Pezzè (Eds.). IEEE Computer Society, 925--935. DOI:https://doi.org/10.1109/ICSE.2012.6227127Google ScholarGoogle Scholar
  30. Bernhard Scholz, Herbert Jordan, Pavle Subotic, and Till Westmann. 2016. On fast large-scale program analysis in Datalog. In Proceedings of the 25th International Conference on Compiler Construction (CC’16), Ayal Zaks and Manuel V. Hermenegildo (Eds.). ACM, 196--206. DOI:https://doi.org/10.1145/2892208.2892226Google ScholarGoogle ScholarDigital LibraryDigital Library
  31. Lei Shang, Xinwei Xie, and Jingling Xue. 2012. On-demand dynamic summary-based points-to analysis. In Proceedings of the 10th IEEE/ACM International Symposium on Code Generation and Optimization (CGO’12). ACM, 264--274. DOI:https://doi.org/10.1145/2259016.2259050Google ScholarGoogle ScholarDigital LibraryDigital Library
  32. Micha Sharir and Amir Pnueli. 1981. Two Approaches to Interprocedural Data Flow Analysis. Prentice-Hall, Chapter 7, 189--234.Google ScholarGoogle Scholar
  33. Olin Shivers. 1991. Control-flow Analysis of Higher-order Languages. Ph.D. Dissertation. Carnegie Mellon University.Google ScholarGoogle Scholar
  34. Yannis Smaragdakis and George Balatsouras. 2015. Pointer analysis. Found. Trends Program. Lang. 2, 1 (2015), 1--69. DOI:https://doi.org/10.1561/2500000014Google ScholarGoogle ScholarDigital LibraryDigital Library
  35. Yannis Smaragdakis, George Balatsouras, and George Kastrinis. 2013. Set-based pre-processing for points-to analysis. In Proceedings of the ACM SIGPLAN International Conference on Object Oriented Programming Systems Languages and Applications (OOPSLA’13). ACM, New York, NY, 253--270. DOI:https://doi.org/10.1145/2509136.2509524Google ScholarGoogle ScholarDigital LibraryDigital Library
  36. Yannis Smaragdakis, Martin Bravenboer, and Ondrej Lhoták. 2011. Pick your contexts well: Understanding object-sensitivity. In Proceedings of the 38th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL’11), Thomas Ball and Mooly Sagiv (Eds.). ACM, 17--30. DOI:https://doi.org/10.1145/1926385.1926390Google ScholarGoogle ScholarDigital LibraryDigital Library
  37. Yannis Smaragdakis, George Kastrinis, and George Balatsouras. 2014. Introspective analysis: Context-sensitivity, across the board. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’14), Michael F. P. O’Boyle and Keshav Pingali (Eds.). ACM, 485--495. DOI:https://doi.org/10.1145/2594291.2594320Google ScholarGoogle ScholarDigital LibraryDigital Library
  38. Johannes Späth, Lisa Nguyen Quang Do, Karim Ali, and Eric Bodden. 2016. Boomerang: Demand-driven flow- and context-sensitive pointer analysis for Java. In Proceedings of the 30th European Conference on Object-oriented Programming (ECOOP’16). 22:1–22:26. DOI:https://doi.org/10.4230/LIPIcs.ECOOP.2016.22Google ScholarGoogle Scholar
  39. Manu Sridharan and Rastislav Bodík. 2006. Refinement-based context-sensitive points-to analysis for Java. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation, Michael I. Schwartzbach and Thomas Ball (Eds.). ACM, 387--400. DOI:https://doi.org/10.1145/1133981.1134027Google ScholarGoogle ScholarDigital LibraryDigital Library
  40. Manu Sridharan, Satish Chandra, Julian Dolby, Stephen J. Fink, and Eran Yahav. 2013. Alias analysis for object-oriented programs. In Aliasing in Object-Oriented Programming. Types, Analysis and Verification, Dave Clarke, James Noble, and Tobias Wrigstad (Eds.). Lecture Notes in Computer Science, Vol. 7850. Springer, 196--232. DOI:https://doi.org/10.1007/978-3-642-36946-9_8Google ScholarGoogle ScholarDigital LibraryDigital Library
  41. Manu Sridharan, Stephen J. Fink, and Rastislav Bodík. 2007. Thin slicing. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation, Jeanne Ferrante and Kathryn S. McKinley (Eds.). ACM, 112--122. DOI:https://doi.org/10.1145/1250734.1250748Google ScholarGoogle ScholarDigital LibraryDigital Library
  42. Manu Sridharan, Denis Gopan, Lexin Shan, and Rastislav Bodík. 2005. Demand-driven points-to analysis for Java. In Proceedings of the 20th ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA’05), Ralph E. Johnson and Richard P. Gabriel (Eds.). ACM, 59--76. DOI:https://doi.org/10.1145/1094811.1094817Google ScholarGoogle ScholarDigital LibraryDigital Library
  43. Yulei Sui and Jingling Xue. 2016. On-demand strong update analysis via value-flow refinement. In Proceedings of the 24th ACM SIGSOFT International Symposium on Foundations of Software Engineering (FSE’16). ACM, New York, NY, 460--473. DOI:https://doi.org/10.1145/2950290.2950296Google ScholarGoogle ScholarDigital LibraryDigital Library
  44. Tian Tan, Yue Li, and Jingling Xue. 2016. Making k-object-sensitive pointer analysis more precise with still k-limiting. In Proceedings of the 23rd International Symposium on Static Analysis (SAS’16) (Lecture Notes in Computer Science), Xavier Rival (Ed.), Vol. 9837. Springer, 489--510. DOI:https://doi.org/10.1007/978-3-662-53413-7_24Google ScholarGoogle ScholarCross RefCross Ref
  45. Tian Tan, Yue Li, and Jingling Xue. 2017. Efficient and precise points-to analysis: Modeling the heap by merging equivalent automata. In Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’17), Albert Cohen and Martin T. Vechev (Eds.). ACM, 278--291. DOI:https://doi.org/10.1145/3062341.3062360Google ScholarGoogle ScholarDigital LibraryDigital Library
  46. Manas Thakur and V. Krishna Nandivada. 2019. Compare less, defer more: Scaling value-contexts based whole-program heap analyses. In Proceedings of the 28th International Conference on Compiler Construction (CC’19). ACM, New York, NY, 135--146. DOI:https://doi.org/10.1145/3302516.3307359Google ScholarGoogle Scholar
  47. Rei Thiessen and Ondřej Lhoták. 2017. Context transformations for pointer analysis. In Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’17). ACM, New York, NY, 263--277. DOI:https://doi.org/10.1145/3062341.3062359Google ScholarGoogle ScholarDigital LibraryDigital Library
  48. Paolo Tonella and Alessandra Potrich. 2005. Reverse Engineering of Object Oriented Code. Springer. DOI:https://doi.org/10.1007/b102522Google ScholarGoogle Scholar
  49. Raja Vallée-Rai, Phong Co, Etienne Gagnon, Laurie J. Hendren, Patrick Lam, and Vijay Sundaresan. 1999. Soot—a Java bytecode optimization framework. In Proceedings of the Conference of the Centre for Advanced Studies on Collaborative Research, Stephen A. MacKay and J. Howard Johnson (Eds.). IBM, 13. DOI:https://doi.org/10.1145/781995.782008Google ScholarGoogle ScholarDigital LibraryDigital Library
  50. WALA. 2018. Watson Libraries for Analysis. Retrieved from http://wala.sf.net.Google ScholarGoogle Scholar
  51. Kai Wang, Aftab Hussain, Zhiqiang Zuo, Guoqing Xu, and Ardalan Amiri Sani. 2017. Graspan: A single-machine disk-based graph system for interprocedural static analyses of large-scale systems code. In Proceedings of the 22nd International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS’17). ACM, New York, NY, 389--404. DOI:https://doi.org/10.1145/3037697.3037744Google ScholarGoogle ScholarDigital LibraryDigital Library
  52. Shiyi Wei and Barbara G. Ryder. 2015. Adaptive context-sensitive analysis for JavaScript. In Proceedings of the 29th European Conference on Object-Oriented Programming (ECOOP’15) (LIPIcs), John Tang Boyland (Ed.), Vol. 37. Schloss Dagstuhl - Leibniz-Zentrum fuer Informatik, 712--734. DOI:https://doi.org/10.4230/LIPIcs.ECOOP.2015.712Google ScholarGoogle Scholar
  53. John Whaley and Monica S. Lam. 2004. Cloning-based context-sensitive pointer alias analysis using binary decision diagrams. In Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI’04). ACM, New York, NY, 131--144. DOI:https://doi.org/10.1145/996841.996859Google ScholarGoogle Scholar
  54. Guoqing Xu and Atanas Rountev. 2008. Merging equivalent contexts for scalable heap-cloning-based context-sensitive points-to analysis. In Proceedings of the International Symposium on Software Testing and Analysis (ISSTA’08). ACM, New York, NY, 225--236. DOI:https://doi.org/10.1145/1390630.1390658Google ScholarGoogle ScholarDigital LibraryDigital Library
  55. Dacong Yan, Guoqing (Harry) Xu, and Atanas Rountev. 2011. Demand-driven context-sensitive alias analysis for Java. In Proceedings of the 20th International Symposium on Software Testing and Analysis (ISSTA’11). ACM, 155--165. DOI:https://doi.org/10.1145/2001420.2001440Google ScholarGoogle ScholarDigital LibraryDigital Library

Index Terms

  1. A Principled Approach to Selective Context Sensitivity for Pointer Analysis

    Recommendations

    Comments

    Login options

    Check if you have access through your login credentials or your institution to get full access on this article.

    Sign in

    Full Access

    • Published in

      cover image ACM Transactions on Programming Languages and Systems
      ACM Transactions on Programming Languages and Systems  Volume 42, Issue 2
      June 2020
      286 pages
      ISSN:0164-0925
      EISSN:1558-4593
      DOI:10.1145/3395960
      Issue’s Table of Contents

      Copyright © 2020 ACM

      Publisher

      Association for Computing Machinery

      New York, NY, United States

      Publication History

      • Published: 19 May 2020
      • Online AM: 7 May 2020
      • Accepted: 1 February 2020
      • Revised: 1 January 2020
      • Received: 1 June 2019
      Published in toplas Volume 42, Issue 2

      Permissions

      Request permissions about this article.

      Request Permissions

      Check for updates

      Qualifiers

      • research-article
      • Research
      • Refereed

    PDF Format

    View or Download as a PDF file.

    PDF

    eReader

    View online with eReader.

    eReader

    HTML Format

    View this article in HTML Format .

    View HTML Format
    About Cookies On This Site

    We use cookies to ensure that we give you the best experience on our website.

    Learn more

    Got it!